xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-score.c (revision 2718af68c3efc72c9769069b5c7f9ed36f6b9def)
1 /* tc-score.c -- Assembler for Score
2    Copyright (C) 2006-2020 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 
27 static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED);
28 static void s3_s_score_text (int ignore);
29 static void s3_score_s_section (int ignore);
30 static void s3_s_change_sec (int sec);
31 static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED);
32 static void s3_s_score_ent (int aent);
33 static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED);
34 static void s3_s_score_end (int x ATTRIBUTE_UNUSED);
35 static void s3_s_score_set (int x ATTRIBUTE_UNUSED);
36 static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED);
37 static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
38 static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED);
39 static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
40 static void s3_s_score_lcomm (int bytes_p);
41 
42 static void s_score_bss (int ignore ATTRIBUTE_UNUSED);
43 static void s_score_text (int ignore);
44 static void s_section (int ignore);
45 static void s_change_sec (int sec);
46 static void s_score_mask (int reg_type ATTRIBUTE_UNUSED);
47 static void s_score_ent (int aent);
48 static void s_score_frame (int ignore ATTRIBUTE_UNUSED);
49 static void s_score_end (int x ATTRIBUTE_UNUSED);
50 static void s_score_set (int x ATTRIBUTE_UNUSED);
51 static void s_score_cpload (int ignore ATTRIBUTE_UNUSED);
52 static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
53 static void s_score_gpword (int ignore ATTRIBUTE_UNUSED);
54 static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
55 static void s_score_lcomm (int bytes_p);
56 
57 /* s3: hooks.  */
58 static void s3_md_number_to_chars (char *buf, valueT val, int n);
59 static valueT s3_md_chars_to_number (char *buf, int n);
60 static void s3_assemble (char *str);
61 static void s3_operand (expressionS *);
62 static void s3_begin (void);
63 static void s3_number_to_chars (char *buf, valueT val, int n);
64 static const char *s3_atof (int type, char *litP, int *sizeP);
65 static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED);
66 static void s3_validate_fix (fixS *fixP);
67 static int s3_force_relocation (struct fix *fixp);
68 static bfd_boolean s3_fix_adjustable (fixS * fixP);
69 static void s3_elf_final_processing (void);
70 static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED);
71 static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED);
72 static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp);
73 static long s3_pcrel_from (fixS * fixP);
74 static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size);
75 static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg);
76 static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp);
77 
78 /* s3: utils.  */
79 static void s3_do_ldst_insn (char *);
80 static void s3_do_crdcrscrsimm5 (char *);
81 static void s3_do_ldst_unalign (char *);
82 static void s3_do_ldst_atomic (char *);
83 static void s3_do_ldst_cop (char *);
84 static void s3_do_macro_li_rdi32 (char *);
85 static void s3_do_macro_la_rdi32 (char *);
86 static void s3_do_macro_rdi32hi (char *);
87 static void s3_do_macro_rdi32lo (char *);
88 static void s3_do_macro_mul_rdrsrs (char *);
89 static void s3_do_macro_bcmp (char *);
90 static void s3_do_macro_bcmpz (char *);
91 static void s3_do_macro_ldst_label (char *);
92 static void s3_do_branch (char *);
93 static void s3_do_jump (char *);
94 static void s3_do_empty (char *);
95 static void s3_do16_int (char *);
96 static void s3_do_rdrsrs (char *);
97 static void s3_do_rdsi16 (char *);
98 static void s3_do_rdrssi14 (char *);
99 static void s3_do_sub_rdsi16 (char *);
100 static void s3_do_sub_rdi16 (char *);
101 static void s3_do_sub_rdrssi14 (char *);
102 static void s3_do_rdrsi5 (char *);
103 static void s3_do_rdrsi14 (char *);
104 static void s3_do_rdi16 (char *);
105 static void s3_do_ldis (char *);
106 static void s3_do_xrsi5 (char *);
107 static void s3_do_rdrs (char *);
108 static void s3_do_rdxrs (char *);
109 static void s3_do_rsrs (char *);
110 static void s3_do_rdcrs (char *);
111 static void s3_do_rdsrs (char *);
112 static void s3_do_rd (char *);
113 static void s3_do16_dsp (char *);
114 static void s3_do16_dsp2 (char *);
115 static void s3_do_dsp (char *);
116 static void s3_do_dsp2 (char *);
117 static void s3_do_dsp3 (char *);
118 static void s3_do_rs (char *);
119 static void s3_do_i15 (char *);
120 static void s3_do_xi5x (char *);
121 static void s3_do_ceinst (char *);
122 static void s3_do_cache (char *);
123 static void s3_do16_rdrs2 (char *);
124 static void s3_do16_br (char *);
125 static void s3_do16_brr (char *);
126 static void s3_do_ltb (char *);
127 static void s3_do16_mv_cmp (char *);
128 static void s3_do16_addi (char *);
129 static void s3_do16_cmpi (char *);
130 static void s3_do16_rdi5 (char *);
131 static void s3_do16_xi5 (char *);
132 static void s3_do16_ldst_insn (char *);
133 static void s3_do16_slli_srli (char *);
134 static void s3_do16_ldiu (char *);
135 static void s3_do16_push_pop (char *);
136 static void s3_do16_rpush (char *);
137 static void s3_do16_rpop (char *);
138 static void s3_do16_branch (char *);
139 static void s3_do_lw48 (char *);
140 static void s3_do_sw48 (char *);
141 static void s3_do_ldi48 (char *);
142 static void s3_do_sdbbp48 (char *);
143 static void s3_do_and48 (char *);
144 static void s3_do_or48 (char *);
145 static void s3_do_mbitclr (char *);
146 static void s3_do_mbitset (char *);
147 static void s3_do_rdi16_pic (char *);
148 static void s3_do_addi_s_pic (char *);
149 static void s3_do_addi_u_pic (char *);
150 static 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.  */
185 const char comment_chars[] = "#";
186 const char line_comment_chars[] = "#";
187 const char line_separator_chars[] = ";";
188 /* Chars that can be used to separate mant from exp in floating point numbers.  */
189 const char EXP_CHARS[] = "eE";
190 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
191 
192 #ifdef OBJ_ELF
193 /* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
194 symbolS *GOT_symbol;
195 #endif
196 
197 const 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 
223 const char *md_shortopts = "nO::g::G:";
224 struct 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 
246 size_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.  */
312 enum 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 
321 enum s3_score_pic_level
322 {
323   s3_NO_PIC,
324   s3_PIC
325 };
326 static enum s3_score_pic_level s3_score_pic = s3_NO_PIC;
327 
328 enum s3_insn_type_for_dependency
329 {
330   s3_D_mtcr,
331   s3_D_all_insn
332 };
333 
334 struct s3_insn_to_dependency
335 {
336   const char *insn_name;
337   enum s3_insn_type_for_dependency type;
338 };
339 
340 struct 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 
351 static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] =
352 {
353   /* move special instruction.  */
354   {"mtcr",      s3_D_mtcr},
355 };
356 
357 static 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.  */
364 static char s3_err_msg[255];
365 
366 static int s3_fix_data_dependency = 0;
367 static int s3_warn_fix_data_dependency = 1;
368 
369 static int s3_in_my_get_expression = 0;
370 
371 /* Default, pop warning message when using r1.  */
372 static int s3_nor1 = 1;
373 
374 /* Default will do instruction relax, -O0 will set s3_g_opt = 0.  */
375 static unsigned int s3_g_opt = 1;
376 
377 /* The size of the small data section.  */
378 static unsigned int s3_g_switch_value = 8;
379 
380 static segT s3_pdr_seg;
381 
382 struct 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 };
401 static struct s3_score_it s3_inst;
402 
403 typedef 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;
414 static s3_procS s3_cur_proc;
415 static s3_procS *s3_cur_proc_ptr;
416 static int s3_numprocs;
417 
418 
419 /* Structure for a hash table entry for a register.  */
420 struct s3_reg_entry
421 {
422   const char *name;
423   int number;
424 };
425 
426 static 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 
439 static const struct s3_reg_entry s3_score_srn_table[] =
440 {
441   {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
442   {NULL, 0}
443 };
444 
445 static 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 
458 struct s3_reg_map
459 {
460   const struct s3_reg_entry *names;
461   int max_regno;
462   struct hash_control *htab;
463   const char *expected;
464 };
465 
466 static 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 
473 static struct hash_control *s3_score_ops_hsh = NULL;
474 static struct hash_control *s3_dependency_insn_hsh = NULL;
475 
476 
477 struct s3_datafield_range
478 {
479   int data_type;
480   int bits;
481   int range[2];
482 };
483 
484 static 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 
538 struct 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 
559 static 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 
587 static 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 
1006 static int s3_university_version = 0;
1007 static int s3_vector_size = s3_SCORE3_PIPELINE;
1008 static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE];
1009 
1010 static int s3_score3d = 1;
1011 
1012 static int
1013 s3_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 
1029 static int
1030 s3_score_reg_parse (char **ccp, struct hash_control *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 *) 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 
1060 static int
1061 s3_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 
1099 static int
1100 s3_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 
1126 static void
1127 s3_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 
1169 static int
1170 s3_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 
1183 static int
1184 s3_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.  */
1240 static bfd_signed_vma
1241 s3_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 
1337 static int
1338 s3_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.  */
1566 static void
1567 s3_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 
1634 static void
1635 s3_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.  */
1647 static void
1648 s3_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.  */
1659 static void
1660 s3_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.  */
1671 static void
1672 s3_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.  */
1684 static void
1685 s3_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) */
1699 static void
1700 s3_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)  */
1724 static void
1725 s3_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.  */
1738 static void
1739 s3_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.  */
1759 static void
1760 s3_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 
1807 static void
1808 s3_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 
1818 static void
1819 s3_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.  */
1830 static void
1831 s3_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 .  */
1842 static void
1843 s3_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 .  */
1854 static void
1855 s3_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.  */
1866 static void
1867 s3_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 */
1876 static void
1877 s3_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 
1894 static void
1895 s3_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 
1903 static void
1904 s3_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 
1918 static void
1919 s3_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.  */
1951 static void
1952 s3_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.  */
1963 static void
1964 s3_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.  */
1985 static void
1986 s3_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>.  */
2007 static void
2008 s3_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 
2027 static void
2028 s3_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 
2056 static int
2057 s3_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!.  */
2087 static void
2088 s3_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!.  */
2102 static void
2103 s3_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!.  */
2115 static void
2116 s3_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 */
2130 static void
2131 s3_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.  */
2168 static fixS *
2169 s3_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 
2188 static void
2189 s3_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 
2199 static enum s3_insn_type_for_dependency
2200 s3_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 *) hash_find (s3_dependency_insn_hsh, name);
2207 
2208   if (tmp)
2209     return tmp->type;
2210 
2211   return s3_D_all_insn;
2212 }
2213 
2214 static int
2215 s3_check_dependency (char *pre_insn, char *pre_reg,
2216 		     char *cur_insn, char *cur_reg, int *warn_or_error)
2217 {
2218   int bubbles = 0;
2219   unsigned int i;
2220   enum s3_insn_type_for_dependency pre_insn_type;
2221   enum s3_insn_type_for_dependency cur_insn_type;
2222 
2223   pre_insn_type = s3_dependency_type_from_insn (pre_insn);
2224   cur_insn_type = s3_dependency_type_from_insn (cur_insn);
2225 
2226   for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++)
2227     {
2228       if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type)
2229           && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type
2230               || cur_insn_type == s3_data_dependency_table[i].cur_insn_type)
2231           && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0
2232               || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0)
2233           && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0
2234               || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0))
2235         {
2236           bubbles = s3_data_dependency_table[i].bubblenum_3;
2237           *warn_or_error = s3_data_dependency_table[i].warn_or_error;
2238           break;
2239         }
2240     }
2241 
2242   return bubbles;
2243 }
2244 
2245 static void
2246 s3_build_one_frag (struct s3_score_it one_inst)
2247 {
2248   char *p;
2249   int relaxable_p = s3_g_opt;
2250   int relax_size = 0;
2251 
2252   /* Start a new frag if frag_now is not empty.  */
2253   if (frag_now_fix () != 0)
2254     {
2255       if (!frag_now->tc_frag_data.is_insn)
2256 	frag_wane (frag_now);
2257 
2258       frag_new (0);
2259     }
2260   frag_grow (20);
2261 
2262   p = frag_more (one_inst.size);
2263   s3_md_number_to_chars (p, one_inst.instruction, one_inst.size);
2264 
2265 #ifdef OBJ_ELF
2266   dwarf2_emit_insn (one_inst.size);
2267 #endif
2268 
2269   relaxable_p &= (one_inst.relax_size != 0);
2270   relax_size = relaxable_p ? one_inst.relax_size : 0;
2271 
2272   p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2273                 s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2274 				 one_inst.type, 0, 0, relaxable_p),
2275                 NULL, 0, NULL);
2276 
2277   if (relaxable_p)
2278     s3_md_number_to_chars (p, one_inst.relax_inst, relax_size);
2279 }
2280 
2281 static void
2282 s3_handle_dependency (struct s3_score_it *theinst)
2283 {
2284   int i;
2285   int warn_or_error = 0;   /* warn - 0; error - 1  */
2286   int bubbles = 0;
2287   int remainder_bubbles = 0;
2288   char cur_insn[s3_INSN_NAME_LEN];
2289   char pre_insn[s3_INSN_NAME_LEN];
2290   struct s3_score_it nop_inst;
2291   struct s3_score_it pflush_inst;
2292 
2293   nop_inst.instruction = 0x0000;
2294   nop_inst.size = 2;
2295   nop_inst.relax_inst = 0x80008000;
2296   nop_inst.relax_size = 4;
2297   nop_inst.type = NO16_OPD;
2298 
2299   pflush_inst.instruction = 0x8000800a;
2300   pflush_inst.size = 4;
2301   pflush_inst.relax_inst = 0x8000;
2302   pflush_inst.relax_size = 0;
2303   pflush_inst.type = NO_OPD;
2304 
2305   /* pflush will clear all data dependency.  */
2306   if (strcmp (theinst->name, "pflush") == 0)
2307     {
2308       s3_init_dependency_vector ();
2309       return;
2310     }
2311 
2312   /* Push current instruction to s3_dependency_vector[0].  */
2313   for (i = s3_vector_size - 1; i > 0; i--)
2314     memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i]));
2315 
2316   memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i]));
2317 
2318   /* There is no dependency between nop and any instruction.  */
2319   if (strcmp (s3_dependency_vector[0].name, "nop") == 0
2320       || strcmp (s3_dependency_vector[0].name, "nop!") == 0)
2321     return;
2322 
2323   strcpy (cur_insn, s3_dependency_vector[0].name);
2324 
2325   for (i = 1; i < s3_vector_size; i++)
2326     {
2327       /* The element of s3_dependency_vector is NULL.  */
2328       if (s3_dependency_vector[i].name[0] == '\0')
2329 	continue;
2330 
2331       strcpy (pre_insn, s3_dependency_vector[i].name);
2332 
2333       bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg,
2334 				     cur_insn, s3_dependency_vector[0].reg, &warn_or_error);
2335       remainder_bubbles = bubbles - i + 1;
2336 
2337       if (remainder_bubbles > 0)
2338         {
2339           int j;
2340 
2341           if (s3_fix_data_dependency == 1)
2342             {
2343 	      if (remainder_bubbles <= 2)
2344 		{
2345 		  if (s3_warn_fix_data_dependency)
2346 		    as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2347 			     s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2348 			     s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2349 			     remainder_bubbles, bubbles);
2350 
2351                   for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2352 		    memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles],
2353 			    sizeof (s3_dependency_vector[j]));
2354 
2355                   for (j = 1; j <= remainder_bubbles; j++)
2356                     {
2357                       memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
2358 		      /* Insert nop!.  */
2359     		      s3_build_one_frag (nop_inst);
2360                     }
2361 		}
2362 	      else
2363 		{
2364 		  if (s3_warn_fix_data_dependency)
2365 		    as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2366 			     s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2367 			     s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2368 			     bubbles);
2369 
2370                   for (j = 1; j < s3_vector_size; j++)
2371 		    memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
2372 
2373                   /* Insert pflush.  */
2374                   s3_build_one_frag (pflush_inst);
2375 		}
2376             }
2377           else
2378             {
2379 	      if (warn_or_error)
2380 		{
2381                   as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2382 			  s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2383 			  s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2384 			  remainder_bubbles, bubbles);
2385 		}
2386 	      else
2387 		{
2388                   as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2389                            s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2390                            s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2391                            remainder_bubbles, bubbles);
2392 		}
2393             }
2394         }
2395     }
2396 }
2397 
2398 static enum insn_class
2399 s3_get_insn_class_from_type (enum score_insn_type type)
2400 {
2401   enum insn_class retval = (int) s3_FAIL;
2402 
2403   switch (type)
2404     {
2405     case Rd_I4:
2406     case Rd_I5:
2407     case Rd_rvalueBP_I5:
2408     case Rd_lvalueBP_I5:
2409     case Rd_I8:
2410     case PC_DISP8div2:
2411     case PC_DISP11div2:
2412     case Rd_Rs:
2413     case Rd_HighRs:
2414     case Rd_lvalueRs:
2415     case Rd_rvalueRs:
2416     case x_Rs:
2417     case Rd_LowRs:
2418     case NO16_OPD:
2419     case Rd_SI5:
2420     case Rd_SI6:
2421       retval = INSN_CLASS_16;
2422       break;
2423     case Rd_Rs_I5:
2424     case x_Rs_I5:
2425     case x_I5_x:
2426     case Rd_Rs_I14:
2427     case I15:
2428     case Rd_I16:
2429     case Rd_SI16:
2430     case Rd_rvalueRs_SI10:
2431     case Rd_lvalueRs_SI10:
2432     case Rd_rvalueRs_preSI12:
2433     case Rd_rvalueRs_postSI12:
2434     case Rd_lvalueRs_preSI12:
2435     case Rd_lvalueRs_postSI12:
2436     case Rd_Rs_SI14:
2437     case Rd_rvalueRs_SI15:
2438     case Rd_lvalueRs_SI15:
2439     case PC_DISP19div2:
2440     case PC_DISP24div2:
2441     case Rd_Rs_Rs:
2442     case x_Rs_x:
2443     case x_Rs_Rs:
2444     case Rd_Rs_x:
2445     case Rd_x_Rs:
2446     case Rd_x_x:
2447     case OP5_rvalueRs_SI15:
2448     case I5_Rs_Rs_I5_OP5:
2449     case x_rvalueRs_post4:
2450     case Rd_rvalueRs_post4:
2451     case Rd_x_I5:
2452     case Rd_lvalueRs_post4:
2453     case x_lvalueRs_post4:
2454     case Rd_Rs_Rs_imm:
2455     case NO_OPD:
2456     case Rd_lvalue32Rs:
2457     case Rd_rvalue32Rs:
2458     case Insn_GP:
2459     case Insn_PIC:
2460     case Insn_internal:
2461     case Insn_BCMP:
2462     case Ra_I9_I5:
2463       retval = INSN_CLASS_32;
2464       break;
2465     case Insn_Type_PCE:
2466       retval = INSN_CLASS_PCE;
2467       break;
2468     case Insn_Type_SYN:
2469       retval = INSN_CLASS_SYN;
2470       break;
2471     case Rd_I30:
2472     case Rd_I32:
2473       retval = INSN_CLASS_48;
2474       break;
2475     default:
2476       abort ();
2477       break;
2478     }
2479   return retval;
2480 }
2481 
2482 /* Type of p-bits:
2483    48-bit instruction: 1, 1, 0.
2484    32-bit instruction: 1, 0.
2485    16-bit instruction: 0.  */
2486 static bfd_vma
2487 s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class)
2488 {
2489   bfd_vma result = 0;
2490   bfd_vma m_code_high = 0;
2491   unsigned long m_code_middle = 0;
2492   unsigned long m_code_low = 0;
2493   bfd_vma pb_high = 0;
2494   unsigned long pb_middle = 0;
2495   unsigned long pb_low = 0;
2496 
2497   if (i_class == INSN_CLASS_48)
2498     {
2499       pb_high = 0x800000000000LL;
2500       pb_middle = 0x80000000;
2501       pb_low = 0x00000000;
2502       m_code_high = m_code & 0x1fffc0000000LL;
2503       m_code_middle = m_code & 0x3fff8000;
2504       m_code_low = m_code & 0x00007fff;
2505       result = pb_high | (m_code_high << 2) |
2506 	pb_middle | (m_code_middle << 1) |
2507 	pb_low | m_code_low;
2508     }
2509   else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN)
2510     {
2511       pb_high = 0x80000000;
2512       pb_low = 0x00000000;
2513       m_code_high = m_code & 0x3fff8000;
2514       m_code_low = m_code & 0x00007fff;
2515       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2516     }
2517   else if (i_class == INSN_CLASS_16)
2518     {
2519       pb_high = 0;
2520       pb_low = 0;
2521       m_code_high = m_code & 0x3fff8000;
2522       m_code_low = m_code & 0x00007fff;
2523       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2524     }
2525   else if (i_class == INSN_CLASS_PCE)
2526     {
2527       /* Keep original.  */
2528       pb_high = 0;
2529       pb_low = 0x00008000;
2530       m_code_high = m_code & 0x3fff8000;
2531       m_code_low = m_code & 0x00007fff;
2532       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2533     }
2534   else
2535     {
2536       abort ();
2537     }
2538 
2539   return result;
2540 }
2541 
2542 static void
2543 s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2)
2544 {
2545   char *p;
2546   bfd_boolean pce_p = FALSE;
2547   int relaxable_p = s3_g_opt;
2548   int relax_size = 0;
2549   struct s3_score_it *inst1 = part_1;
2550   struct s3_score_it *inst2 = part_2;
2551   struct s3_score_it backup_inst1;
2552 
2553   pce_p = (inst2) ? TRUE : FALSE;
2554   memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it));
2555 
2556   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
2557   if (pce_p)
2558     {
2559       backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2560 	| (inst2->instruction & 0x7FFF);
2561       backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2562       backup_inst1.relax_inst = 0x8000;
2563       backup_inst1.size = s3_INSN_SIZE;
2564       backup_inst1.relax_size = 0;
2565       backup_inst1.type = Insn_Type_PCE;
2566     }
2567   else
2568     {
2569       backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction,
2570 						      s3_GET_INSN_CLASS (backup_inst1.type));
2571     }
2572 
2573   if (backup_inst1.relax_size != 0)
2574     {
2575       enum insn_class tmp;
2576 
2577       tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2578       backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp);
2579     }
2580 
2581   /* Check data dependency.  */
2582   s3_handle_dependency (&backup_inst1);
2583 
2584   /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2585      data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
2586   if (frag_now_fix () != 0)
2587     {
2588       if (!frag_now->tc_frag_data.is_insn)
2589 	frag_wane (frag_now);
2590 
2591       frag_new (0);
2592     }
2593 
2594   /* Here, we must call frag_grow in order to keep the instruction frag type is
2595      rs_machine_dependent.
2596      For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2597      actually will call frag_wane.
2598      Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2599      for frag_var.  */
2600   frag_grow (20);
2601 
2602   p = frag_more (backup_inst1.size);
2603   s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2604 
2605 #ifdef OBJ_ELF
2606   dwarf2_emit_insn (backup_inst1.size);
2607 #endif
2608 
2609   /* Generate fixup structure.  */
2610   if (pce_p)
2611     {
2612       if (inst1->reloc.type != BFD_RELOC_NONE)
2613 	s3_fix_new_score (frag_now, p - frag_now->fr_literal,
2614 			  inst1->size, &inst1->reloc.exp,
2615 			  inst1->reloc.pc_rel, inst1->reloc.type);
2616 
2617       if (inst2->reloc.type != BFD_RELOC_NONE)
2618 	s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2619 			  inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2620     }
2621   else
2622     {
2623       if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2624 	s3_fix_new_score (frag_now, p - frag_now->fr_literal,
2625 			  backup_inst1.size, &backup_inst1.reloc.exp,
2626 			  backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2627     }
2628 
2629   /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
2630   relaxable_p &= (backup_inst1.relax_size != 0);
2631   relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2632 
2633   p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2634                 s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2635 				 backup_inst1.type, 0, 0, relaxable_p),
2636                 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2637 
2638   if (relaxable_p)
2639     s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2640 
2641   memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it));
2642 }
2643 
2644 static void
2645 s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2646 {
2647   char c;
2648   char *p;
2649   char *operator = insnstr;
2650   const struct s3_asm_opcode *opcode;
2651 
2652   /* Parse operator and operands.  */
2653   s3_skip_whitespace (operator);
2654 
2655   for (p = operator; *p != '\0'; p++)
2656     if ((*p == ' ') || (*p == '!'))
2657       break;
2658 
2659   if (*p == '!')
2660     p++;
2661 
2662   c = *p;
2663   *p = '\0';
2664 
2665   opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
2666   *p = c;
2667 
2668   memset (&s3_inst, '\0', sizeof (s3_inst));
2669   sprintf (s3_inst.str, "%s", insnstr);
2670   if (opcode)
2671     {
2672       s3_inst.instruction = opcode->value;
2673       s3_inst.relax_inst = opcode->relax_value;
2674       s3_inst.type = opcode->type;
2675       s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2676       s3_inst.relax_size = 0;
2677       s3_inst.bwarn = 0;
2678       sprintf (s3_inst.name, "%s", opcode->template_name);
2679       strcpy (s3_inst.reg, "");
2680       s3_inst.error = NULL;
2681       s3_inst.reloc.type = BFD_RELOC_NONE;
2682 
2683       (*opcode->parms) (p);
2684 
2685       /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1.  */
2686       if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2687 	s3_gen_insn_frag (&s3_inst, NULL);
2688     }
2689   else
2690     s3_inst.error = _("unrecognized opcode");
2691 }
2692 
2693 static void
2694 s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p)
2695 {
2696   char c;
2697   char *p;
2698   char *operator = insnstr;
2699   const struct s3_asm_opcode *opcode;
2700 
2701   /* Parse operator and operands.  */
2702   s3_skip_whitespace (operator);
2703 
2704   for (p = operator; *p != '\0'; p++)
2705     if (*p == ' ')
2706       break;
2707 
2708   c = *p;
2709   *p = '\0';
2710 
2711   opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
2712   *p = c;
2713 
2714   memset (&s3_inst, '\0', sizeof (s3_inst));
2715   sprintf (s3_inst.str, "%s", insnstr);
2716   if (opcode)
2717     {
2718       s3_inst.instruction = opcode->value;
2719       s3_inst.relax_inst = opcode->relax_value;
2720       s3_inst.type = opcode->type;
2721       s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2722       s3_inst.relax_size = 0;
2723       s3_inst.bwarn = 0;
2724       sprintf (s3_inst.name, "%s", opcode->template_name);
2725       strcpy (s3_inst.reg, "");
2726       s3_inst.error = NULL;
2727       s3_inst.reloc.type = BFD_RELOC_NONE;
2728 
2729       (*opcode->parms) (p);
2730 
2731       /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1.  */
2732       if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2733 	s3_gen_insn_frag (&s3_inst, NULL);
2734     }
2735   else
2736     s3_inst.error = _("unrecognized opcode");
2737 }
2738 
2739 static int
2740 s3_append_insn (char *str, bfd_boolean gen_frag_p)
2741 {
2742   int retval = s3_SUCCESS;
2743 
2744   s3_parse_16_32_inst (str, gen_frag_p);
2745 
2746   if (s3_inst.error)
2747     {
2748       retval = (int) s3_FAIL;
2749       as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
2750       s3_inst.error = NULL;
2751     }
2752 
2753   return retval;
2754 }
2755 
2756 static void
2757 s3_do16_mv_cmp (char *str)
2758 {
2759   s3_skip_whitespace (str);
2760 
2761   if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2762       || s3_skip_past_comma (&str) == (int) s3_FAIL
2763       || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2764       || s3_end_of_line (str) == (int) s3_FAIL)
2765     {
2766       return;
2767     }
2768 }
2769 
2770 static void
2771 s3_do16_cmpi (char *str)
2772 {
2773   s3_skip_whitespace (str);
2774 
2775   if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2776       || s3_skip_past_comma (&str) == (int) s3_FAIL
2777       || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL
2778       || s3_end_of_line (str) == (int) s3_FAIL)
2779     {
2780       return;
2781     }
2782 }
2783 
2784 static void
2785 s3_do16_addi (char *str)
2786 {
2787   s3_skip_whitespace (str);
2788 
2789   if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL
2790       || s3_skip_past_comma (&str) == (int) s3_FAIL
2791       || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL
2792       || s3_end_of_line (str) == (int) s3_FAIL)
2793     {
2794       return;
2795     }
2796 }
2797 
2798 /* Handle bitclr! / bitset! / bittst! / bittgl! */
2799 static void
2800 s3_do16_rdi5 (char *str)
2801 {
2802   s3_skip_whitespace (str);
2803 
2804   if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL
2805       || s3_skip_past_comma (&str) == (int) s3_FAIL
2806       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
2807       || s3_end_of_line (str) == (int) s3_FAIL)
2808     return;
2809   else
2810     {
2811       s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20)
2812         | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10);
2813       s3_inst.relax_size = 4;
2814     }
2815 }
2816 
2817 
2818 /* Handle sdbbp!.  */
2819 static void
2820 s3_do16_xi5 (char *str)
2821 {
2822   s3_skip_whitespace (str);
2823 
2824   if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
2825     return;
2826 }
2827 
2828 /* Check that an immediate is word alignment or half word alignment.
2829    If so, convert it to the right format.  */
2830 static int
2831 s3_validate_immediate_align (int val, unsigned int data_type)
2832 {
2833   if (data_type == _IMM5_RSHIFT_1)
2834     {
2835       if (val % 2)
2836         {
2837           s3_inst.error = _("address offset must be half word alignment");
2838           return (int) s3_FAIL;
2839         }
2840     }
2841   else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2842     {
2843       if (val % 4)
2844         {
2845           s3_inst.error = _("address offset must be word alignment");
2846           return (int) s3_FAIL;
2847         }
2848     }
2849 
2850   return s3_SUCCESS;
2851 }
2852 
2853 static int
2854 s3_exp_ldst_offset (char **str, int shift, unsigned int data_type)
2855 {
2856   char *dataptr;
2857 
2858   dataptr = * str;
2859 
2860   if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2861       && (data_type != _SIMM16_LA)
2862       && (data_type != _VALUE_HI16)
2863       && (data_type != _VALUE_LO16)
2864       && (data_type != _IMM16)
2865       && (data_type != _IMM15)
2866       && (data_type != _IMM14)
2867       && (data_type != _IMM4)
2868       && (data_type != _IMM5)
2869       && (data_type != _IMM8)
2870       && (data_type != _IMM5_RSHIFT_1)
2871       && (data_type != _IMM5_RSHIFT_2)
2872       && (data_type != _SIMM14_NEG)
2873       && (data_type != _IMM10_RSHIFT_2))
2874     {
2875       data_type += 24;
2876     }
2877 
2878   if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
2879     return (int) s3_FAIL;
2880 
2881   if (s3_inst.reloc.exp.X_op == O_constant)
2882     {
2883       /* Need to check the immediate align.  */
2884       int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type);
2885 
2886       if (value == (int) s3_FAIL)
2887 	return (int) s3_FAIL;
2888 
2889       value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
2890       if (value == (int) s3_FAIL)
2891         {
2892           if (data_type < 30)
2893             sprintf (s3_err_msg,
2894                      _("invalid constant: %d bit expression not in range %d..%d"),
2895                      s3_score_df_range[data_type].bits,
2896                      s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
2897           else
2898             sprintf (s3_err_msg,
2899                      _("invalid constant: %d bit expression not in range %d..%d"),
2900                      s3_score_df_range[data_type - 24].bits,
2901                      s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]);
2902           s3_inst.error = s3_err_msg;
2903           return (int) s3_FAIL;
2904         }
2905 
2906       if (data_type == _IMM5_RSHIFT_1)
2907         {
2908           value >>= 1;
2909         }
2910       else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2911         {
2912           value >>= 2;
2913         }
2914 
2915       if (s3_score_df_range[data_type].range[0] != 0)
2916         {
2917           value &= (1 << s3_score_df_range[data_type].bits) - 1;
2918         }
2919 
2920       s3_inst.instruction |= value << shift;
2921     }
2922   else
2923     {
2924       s3_inst.reloc.pc_rel = 0;
2925     }
2926 
2927   return s3_SUCCESS;
2928 }
2929 
2930 static void
2931 s3_do_ldst_insn (char *str)
2932 {
2933   int pre_inc = 0;
2934   int conflict_reg;
2935   int value;
2936   char * temp;
2937   char *dataptr;
2938   int reg;
2939   int ldst_idx = 0;
2940 
2941   s3_skip_whitespace (str);
2942 
2943   if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
2944       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
2945     return;
2946 
2947   /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
2948   if (*str == '[')
2949     {
2950       str++;
2951       s3_skip_whitespace (str);
2952 
2953       if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
2954 	return;
2955 
2956       /* Conflicts can occur on stores as well as loads.  */
2957       conflict_reg = (conflict_reg == reg);
2958       s3_skip_whitespace (str);
2959       temp = str + 1;    /* The latter will process decimal/hex expression.  */
2960 
2961       /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
2962       if (*str == ']')
2963         {
2964           str++;
2965           if (*str == '+')
2966             {
2967               str++;
2968               /* ld/sw rD, [rA]+, simm12.  */
2969               if (s3_skip_past_comma (&str) == s3_SUCCESS)
2970                 {
2971                   if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL)
2972                       || (s3_end_of_line (str) == (int) s3_FAIL))
2973 		    return;
2974 
2975                   if (conflict_reg)
2976                     {
2977                       unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
2978 
2979                       if ((ldst_func == INSN_LH)
2980                           || (ldst_func == INSN_LHU)
2981                           || (ldst_func == INSN_LW)
2982                           || (ldst_func == INSN_LB)
2983                           || (ldst_func == INSN_LBU))
2984                         {
2985                           s3_inst.error = _("register same as write-back base");
2986                           return;
2987                         }
2988                     }
2989 
2990                   ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
2991                   s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2992                   s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2993 
2994                   /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
2995                   if ((s3_inst.instruction & 0x3e000007) == 0x0e000000)
2996                     {
2997                       /* rs =  r0, offset = 4 */
2998                       if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
2999                           && (((s3_inst.instruction >> 3) & 0xfff) == 4))
3000                         {
3001                           /* Relax to pop!.  */
3002                           s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f);
3003                           s3_inst.relax_size = 2;
3004                         }
3005                     }
3006                   return;
3007                 }
3008               /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
3009               else
3010                 {
3011                   s3_SET_INSN_ERROR (NULL);
3012                   if (s3_end_of_line (str) == (int) s3_FAIL)
3013                     {
3014                       return;
3015                     }
3016 
3017                   pre_inc = 1;
3018                   value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0);
3019                   value &= (1 << s3_score_df_range[_SIMM12].bits) - 1;
3020                   ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3021                   s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3022                   s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3023                   s3_inst.instruction |= value << 3;
3024                   s3_inst.relax_inst = 0x8000;
3025                   return;
3026                 }
3027             }
3028           /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
3029           else
3030             {
3031               if (s3_end_of_line (str) == (int) s3_FAIL)
3032 		return;
3033 
3034               ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3035               s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3036               s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3037 
3038               /* lbu rd, [rs] -> lbu! rd, [rs]  */
3039               if (ldst_idx == INSN_LBU)
3040                 {
3041                   s3_inst.relax_inst = INSN16_LBU;
3042                 }
3043               else if (ldst_idx == INSN_LH)
3044                 {
3045                   s3_inst.relax_inst = INSN16_LH;
3046                 }
3047               else if (ldst_idx == INSN_LW)
3048                 {
3049                   s3_inst.relax_inst = INSN16_LW;
3050                 }
3051               else if (ldst_idx == INSN_SB)
3052                 {
3053                   s3_inst.relax_inst = INSN16_SB;
3054                 }
3055               else if (ldst_idx == INSN_SH)
3056                 {
3057                   s3_inst.relax_inst = INSN16_SH;
3058                 }
3059               else if (ldst_idx == INSN_SW)
3060                 {
3061                   s3_inst.relax_inst = INSN16_SW;
3062                 }
3063               else
3064                 {
3065                   s3_inst.relax_inst = 0x8000;
3066                 }
3067 
3068               /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
3069               /* if ((ldst_idx == INSN_LBU)
3070 		 || (ldst_idx == INSN_LH)
3071 		 || (ldst_idx == INSN_LW)
3072 		 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/
3073               if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW))
3074                 {
3075                   /* ra only 3 bit , rd only 4 bit for lw! and sw! */
3076                   if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
3077                     {
3078                       s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) |
3079                         (((s3_inst.instruction >> 15) & 0x7) << 5);
3080                       s3_inst.relax_size = 2;
3081                     }
3082                 }
3083 
3084               return;
3085             }
3086         }
3087       /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
3088       else
3089         {
3090           if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3091             {
3092               s3_inst.error = _("pre-indexed expression expected");
3093               return;
3094             }
3095 
3096           if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3097 	    return;
3098 
3099           s3_skip_whitespace (str);
3100           if (*str++ != ']')
3101             {
3102               s3_inst.error = _("missing ]");
3103               return;
3104             }
3105 
3106           s3_skip_whitespace (str);
3107           /* ld/sw rD, [rA, simm12]+.  */
3108           if (*str == '+')
3109             {
3110               str++;
3111               pre_inc = 1;
3112               if (conflict_reg)
3113                 {
3114                   unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3115 
3116                   if ((ldst_func == INSN_LH)
3117                       || (ldst_func == INSN_LHU)
3118                       || (ldst_func == INSN_LW)
3119                       || (ldst_func == INSN_LB)
3120                       || (ldst_func == INSN_LBU))
3121                     {
3122                       s3_inst.error = _("register same as write-back base");
3123                       return;
3124                     }
3125                 }
3126             }
3127 
3128           if (s3_end_of_line (str) == (int) s3_FAIL)
3129 	    return;
3130 
3131           if (s3_inst.reloc.exp.X_op == O_constant)
3132             {
3133               unsigned int data_type;
3134 
3135               if (pre_inc == 1)
3136                 data_type = _SIMM12;
3137               else
3138                 data_type = _SIMM15;
3139               dataptr = temp;
3140 
3141               if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
3142                   && (data_type != _SIMM16_LA)
3143                   && (data_type != _VALUE_HI16)
3144                   && (data_type != _VALUE_LO16)
3145                   && (data_type != _IMM16)
3146                   && (data_type != _IMM15)
3147                   && (data_type != _IMM14)
3148                   && (data_type != _IMM4)
3149                   && (data_type != _IMM5)
3150                   && (data_type != _IMM8)
3151                   && (data_type != _IMM5_RSHIFT_1)
3152                   && (data_type != _IMM5_RSHIFT_2)
3153                   && (data_type != _SIMM14_NEG)
3154                   && (data_type != _IMM10_RSHIFT_2))
3155                 {
3156                   data_type += 24;
3157                 }
3158 
3159               value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3160               if (value == (int) s3_FAIL)
3161                 {
3162                   if (data_type < 30)
3163                     sprintf (s3_err_msg,
3164                              _("invalid constant: %d bit expression not in range %d..%d"),
3165                              s3_score_df_range[data_type].bits,
3166                              s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3167                   else
3168                     sprintf (s3_err_msg,
3169                              _("invalid constant: %d bit expression not in range %d..%d"),
3170                              s3_score_df_range[data_type - 24].bits,
3171                              s3_score_df_range[data_type - 24].range[0],
3172                              s3_score_df_range[data_type - 24].range[1]);
3173                   s3_inst.error = s3_err_msg;
3174                   return;
3175                 }
3176 
3177               value &= (1 << s3_score_df_range[data_type].bits) - 1;
3178               ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3179               s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3180               s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3181               if (pre_inc == 1)
3182                 s3_inst.instruction |= value << 3;
3183               else
3184                 s3_inst.instruction |= value;
3185 
3186               /* lw rD, [rA, simm15]  */
3187               if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
3188                 {
3189                   /*  rD  in [r0 - r15]. , ra in [r0-r7] */
3190                   if ((((s3_inst.instruction >> 15) & 0x18) == 0)
3191                       && (((s3_inst.instruction >> 20) & 0x10) == 0))
3192                     {
3193                       /* simm = [bit 7], lw -> lw!.  */
3194                       if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3195                         {
3196                           s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5)
3197                             | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3198                           s3_inst.relax_size = 2;
3199                         }
3200                       else
3201                         {
3202                           s3_inst.relax_inst = 0x8000;
3203                         }
3204                     }
3205                   else
3206                     {
3207                       s3_inst.relax_inst = 0x8000;
3208                     }
3209                 }
3210               /* sw rD, [rA, simm15]  */
3211               else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
3212                 {
3213                   /* rD is  in [r0 - r15] and ra in [r0-r7] */
3214                   if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
3215                     {
3216                       /* simm15 =7 bit  , sw -> sw!.  */
3217                       if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3218                         {
3219                           s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5)
3220                             | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3221                           s3_inst.relax_size = 2;
3222                         }
3223                       /* rA = r2, sw -> swp!.  */
3224                       else
3225                         {
3226                           s3_inst.relax_inst = 0x8000;
3227                         }
3228                     }
3229                   else
3230                     {
3231                       s3_inst.relax_inst = 0x8000;
3232                     }
3233                 }
3234               /* sw rD, [rA, simm15]+    sw pre.  */
3235               else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
3236                 {
3237                   /* simm15 = -4. and ra==r0 */
3238                   if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3239                       && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
3240                     {
3241                       /* sw -> push!.  */
3242                       s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
3243                       s3_inst.relax_size = 2;
3244                     }
3245                   else
3246                     {
3247                       s3_inst.relax_inst = 0x8000;
3248                     }
3249                 }
3250               else
3251                 {
3252                   s3_inst.relax_inst = 0x8000;
3253                 }
3254 
3255               return;
3256             }
3257           else
3258             {
3259               /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3260               s3_inst.reloc.pc_rel = 0;
3261             }
3262         }
3263     }
3264   else
3265     {
3266       s3_inst.error = s3_BAD_ARGS;
3267     }
3268 }
3269 
3270 /* Handle cache.  */
3271 static void
3272 s3_do_cache (char *str)
3273 {
3274   s3_skip_whitespace (str);
3275 
3276   if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3277     {
3278       return;
3279     }
3280   else
3281     {
3282       int cache_op;
3283 
3284       cache_op = (s3_inst.instruction >> 20) & 0x1F;
3285       sprintf (s3_inst.name, "cache %d", cache_op);
3286     }
3287 
3288   if (*str == '[')
3289     {
3290       str++;
3291       s3_skip_whitespace (str);
3292 
3293       if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3294 	return;
3295 
3296       s3_skip_whitespace (str);
3297 
3298       /* cache op, [rA]  */
3299       if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3300         {
3301           s3_SET_INSN_ERROR (NULL);
3302           if (*str != ']')
3303             {
3304               s3_inst.error = _("missing ]");
3305               return;
3306             }
3307           str++;
3308         }
3309       /* cache op, [rA, simm15]  */
3310       else
3311         {
3312           if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
3313             {
3314               return;
3315             }
3316 
3317           s3_skip_whitespace (str);
3318           if (*str++ != ']')
3319             {
3320               s3_inst.error = _("missing ]");
3321               return;
3322             }
3323         }
3324 
3325       if (s3_end_of_line (str) == (int) s3_FAIL)
3326 	return;
3327     }
3328   else
3329     {
3330       s3_inst.error = s3_BAD_ARGS;
3331     }
3332 }
3333 
3334 static void
3335 s3_do_crdcrscrsimm5 (char *str)
3336 {
3337   char *strbak;
3338 
3339   strbak = str;
3340   s3_skip_whitespace (str);
3341 
3342   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3343       || s3_skip_past_comma (&str) == (int) s3_FAIL
3344       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3345       || s3_skip_past_comma (&str) == (int) s3_FAIL
3346       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3347       || s3_skip_past_comma (&str) == (int) s3_FAIL)
3348     {
3349       str = strbak;
3350       /* cop1 cop_code20.  */
3351       if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
3352 	return;
3353     }
3354   else
3355     {
3356       if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
3357 	return;
3358     }
3359 
3360   s3_end_of_line (str);
3361 }
3362 
3363 /* Handle ldc/stc.  */
3364 static void
3365 s3_do_ldst_cop (char *str)
3366 {
3367   s3_skip_whitespace (str);
3368 
3369   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL)
3370       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3371     return;
3372 
3373   if (*str == '[')
3374     {
3375       str++;
3376       s3_skip_whitespace (str);
3377 
3378       if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3379 	return;
3380 
3381       s3_skip_whitespace (str);
3382 
3383       if (*str++ != ']')
3384         {
3385           if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
3386 	    return;
3387 
3388           s3_skip_whitespace (str);
3389           if (*str++ != ']')
3390             {
3391               s3_inst.error = _("missing ]");
3392               return;
3393             }
3394         }
3395 
3396       s3_end_of_line (str);
3397     }
3398   else
3399     s3_inst.error = s3_BAD_ARGS;
3400 }
3401 
3402 static void
3403 s3_do16_ldst_insn (char *str)
3404 {
3405   int conflict_reg = 0;
3406   s3_skip_whitespace (str);
3407 
3408   if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3409     return;
3410 
3411   if (*str == '[')
3412     {
3413 
3414       str++;
3415       s3_skip_whitespace (str);
3416 
3417       if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
3418 	return;
3419       if (conflict_reg&0x8)
3420         {
3421           sprintf (s3_err_msg,  _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
3422           s3_inst.error = s3_err_msg;
3423           return;
3424         }
3425 
3426       s3_skip_whitespace (str);
3427 
3428       if (*str == ']')
3429         {
3430           str++;
3431           if (s3_end_of_line (str) == (int) s3_FAIL)
3432 	    return;
3433         }
3434       else
3435         {
3436           if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3437 	    {
3438 	      s3_inst.error = _("comma is  expected");
3439               return;
3440 	    }
3441           if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3442 	    return;
3443           s3_skip_whitespace (str);
3444 	  if (*str++ != ']')
3445 	    {
3446 	      s3_inst.error = _("missing ]");
3447 	      return;
3448 	    }
3449           if (s3_end_of_line (str) == (int) s3_FAIL)
3450 	    return;
3451           if (s3_inst.reloc.exp.X_op == O_constant)
3452             {
3453               int value;
3454 	      unsigned int data_type;
3455               data_type = _IMM5_RSHIFT_2;
3456               value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3457               if (value == (int) s3_FAIL)
3458 		{
3459 		  if (data_type < 30)
3460 		    sprintf (s3_err_msg,
3461 			     _("invalid constant: %d bit expression not in range %d..%d"),
3462 			     s3_score_df_range[data_type].bits,
3463 			     s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3464                   s3_inst.error = s3_err_msg;
3465 	          return;
3466 	        }
3467               if (value & 0x3)
3468                 {
3469                   sprintf (s3_err_msg,  _("invalid constant: %d is not word align integer"),value);
3470                   s3_inst.error = s3_err_msg;
3471                   return;
3472                 }
3473 
3474               value >>= 2;
3475               s3_inst.instruction |= value;
3476             }
3477         }
3478     }
3479   else
3480     {
3481       sprintf (s3_err_msg,  _("missing ["));
3482       s3_inst.error = s3_err_msg;
3483       return;
3484     }
3485 }
3486 
3487 static void
3488 s3_do_lw48 (char *str)
3489 {
3490   bfd_signed_vma val = 0;
3491 
3492   s3_skip_whitespace (str);
3493 
3494   if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3495       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3496     return;
3497 
3498   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3499       || s3_end_of_line (str) == (int) s3_FAIL)
3500     {
3501       return;
3502     }
3503 
3504   /* Check word align for lw48 rd, value.  */
3505   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3506       && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3507     {
3508       s3_inst.error = _("invalid constant: 32 bit expression not word align");
3509       return;
3510     }
3511 
3512   /* Check and set offset.  */
3513   val = s3_inst.reloc.exp.X_add_number;
3514   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3515       && (!(val >= 0 && val <= 0xffffffffLL)))
3516     {
3517       s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3518       return;
3519     }
3520 
3521   val &= 0xffffffff;
3522   val >>= 2;
3523   s3_inst.instruction |= (val << 7);
3524 
3525   /* Set reloc type.  */
3526   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3527 
3528 }
3529 
3530 static void
3531 s3_do_sw48 (char *str)
3532 {
3533   bfd_signed_vma val = 0;
3534 
3535   s3_skip_whitespace (str);
3536 
3537   if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3538       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3539     return;
3540 
3541   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3542       || s3_end_of_line (str) == (int) s3_FAIL)
3543     {
3544       return;
3545     }
3546 
3547   /* Check word align for lw48 rd, value.  */
3548   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3549       && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3550     {
3551       s3_inst.error = _("invalid constant: 32 bit expression not word align");
3552       return;
3553     }
3554 
3555   /* Check and set offset.  */
3556   val = s3_inst.reloc.exp.X_add_number;
3557   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3558       && (!(val >= 0 && val <= 0xffffffffLL)))
3559     {
3560       s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3561       return;
3562     }
3563 
3564   val &= 0xffffffff;
3565   val >>= 2;
3566   s3_inst.instruction |= (val << 7);
3567 
3568   /* Set reloc type.  */
3569   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3570 }
3571 
3572 static void
3573 s3_do_ldi48 (char *str)
3574 {
3575   bfd_signed_vma val;
3576 
3577   s3_skip_whitespace (str);
3578 
3579   if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL
3580       || s3_skip_past_comma (&str) == (int) s3_FAIL)
3581     return;
3582 
3583   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3584       || s3_end_of_line (str) == (int) s3_FAIL)
3585     {
3586       return;
3587     }
3588 
3589   /* Check and set offset.  */
3590   val = s3_inst.reloc.exp.X_add_number;
3591   if (!(val >= -0xffffffffLL && val <= 0xffffffffLL))
3592     {
3593       s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]");
3594       return;
3595     }
3596 
3597   val &= 0xffffffff;
3598   s3_inst.instruction |= (val << 5);
3599 
3600   /* Set reloc type.  */
3601   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32;
3602 }
3603 
3604 static void
3605 s3_do_sdbbp48 (char *str)
3606 {
3607   s3_skip_whitespace (str);
3608 
3609   if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
3610     return;
3611 }
3612 
3613 static void
3614 s3_do_and48 (char *str)
3615 {
3616   s3_skip_whitespace (str);
3617 
3618   if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3619       || s3_skip_past_comma (&str) == (int) s3_FAIL
3620       || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3621       || s3_skip_past_comma (&str) == (int) s3_FAIL
3622       || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3623       || s3_end_of_line (str) == (int) s3_FAIL)
3624     return;
3625 }
3626 
3627 static void
3628 s3_do_or48 (char *str)
3629 {
3630   s3_skip_whitespace (str);
3631 
3632   if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3633       || s3_skip_past_comma (&str) == (int) s3_FAIL
3634       || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3635       || s3_skip_past_comma (&str) == (int) s3_FAIL
3636       || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3637       || s3_end_of_line (str) == (int) s3_FAIL)
3638     return;
3639 }
3640 
3641 static void
3642 s3_do_mbitclr (char *str)
3643 {
3644   int val;
3645   s3_skip_whitespace (str);
3646 
3647   if (*str != '[')
3648     {
3649       sprintf (s3_err_msg,  _("missing ["));
3650       s3_inst.error = s3_err_msg;
3651       return;
3652     }
3653   str++;
3654 
3655   s3_inst.instruction &= 0x0;
3656 
3657   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3658       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3659       || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3660     return;
3661 
3662   /* Get imm11 and refill opcode.  */
3663   val = s3_inst.instruction & 0x7ff;
3664   val >>= 2;
3665   s3_inst.instruction &= 0x000f8000;
3666   s3_inst.instruction |= 0x00000064;
3667 
3668   if (*str != ']')
3669     {
3670       sprintf (s3_err_msg,  _("missing ]"));
3671       s3_inst.error = s3_err_msg;
3672       return;
3673     }
3674   str++;
3675 
3676   if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3677       || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3678     return;
3679 
3680   /* Set imm11 to opcode.  */
3681   s3_inst.instruction |= (val & 0x1)
3682     | (((val >> 1 ) & 0x7) << 7)
3683     | (((val >> 4 ) & 0x1f) << 20);
3684 }
3685 
3686 static void
3687 s3_do_mbitset (char *str)
3688 {
3689   int val;
3690   s3_skip_whitespace (str);
3691 
3692   if (*str != '[')
3693     {
3694       sprintf (s3_err_msg,  _("missing ["));
3695       s3_inst.error = s3_err_msg;
3696       return;
3697     }
3698   str++;
3699 
3700   s3_inst.instruction &= 0x0;
3701 
3702   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3703       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3704       || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3705     return;
3706 
3707   /* Get imm11 and refill opcode.  */
3708   val = s3_inst.instruction & 0x7ff;
3709   val >>= 2;
3710   s3_inst.instruction &= 0x000f8000;
3711   s3_inst.instruction |= 0x0000006c;
3712 
3713   if (*str != ']')
3714     {
3715       sprintf (s3_err_msg,  _("missing ]"));
3716       s3_inst.error = s3_err_msg;
3717       return;
3718     }
3719   str++;
3720 
3721   if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3722       || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3723     return;
3724 
3725   /* Set imm11 to opcode.  */
3726   s3_inst.instruction |= (val & 0x1)
3727     | (((val >> 1 ) & 0x7) << 7)
3728     | (((val >> 4 ) & 0x1f) << 20);
3729 }
3730 
3731 static void
3732 s3_do16_slli_srli (char *str)
3733 {
3734   s3_skip_whitespace (str);
3735 
3736   if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL)
3737       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3738       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3739       || s3_end_of_line (str) == (int) s3_FAIL)
3740     return;
3741 }
3742 
3743 static void
3744 s3_do16_ldiu (char *str)
3745 {
3746   s3_skip_whitespace (str);
3747 
3748   if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3749       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3750       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3751       || s3_end_of_line (str) == (int) s3_FAIL)
3752     return;
3753 }
3754 
3755 static void
3756 s3_do16_push_pop (char *str)
3757 {
3758   s3_skip_whitespace (str);
3759   if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
3760       || s3_end_of_line (str) == (int) s3_FAIL)
3761     return;
3762 }
3763 
3764 static void
3765 s3_do16_rpush (char *str)
3766 {
3767   int reg;
3768   int val;
3769   s3_skip_whitespace (str);
3770   if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3771       || s3_skip_past_comma (&str) == (int) s3_FAIL
3772       || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3773       || s3_end_of_line (str) == (int) s3_FAIL)
3774     return;
3775 
3776   /* 0: indicate 32.
3777      1: invalid value.
3778      2: to 31: normal value.  */
3779   val = s3_inst.instruction & 0x1f;
3780   if (val == 1)
3781     {
3782       s3_inst.error = _("imm5 should >= 2");
3783       return;
3784     }
3785   if (reg >= 32)
3786     {
3787       s3_inst.error = _("reg should <= 31");
3788       return;
3789     }
3790 }
3791 
3792 static void
3793 s3_do16_rpop (char *str)
3794 {
3795   int reg;
3796   int val;
3797   s3_skip_whitespace (str);
3798   if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3799       || s3_skip_past_comma (&str) == (int) s3_FAIL
3800       || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3801       || s3_end_of_line (str) == (int) s3_FAIL)
3802     return;
3803 
3804   /* 0: indicate 32.
3805      1: invalid value.
3806      2: to 31: normal value.  */
3807   val = s3_inst.instruction & 0x1f;
3808   if (val == 1)
3809     {
3810       s3_inst.error = _("imm5 should >= 2");
3811       return;
3812     }
3813 
3814   if (reg >= 32)
3815     {
3816       s3_inst.error = _("reg should <= 31");
3817       return;
3818     }
3819   else
3820     {
3821       if ((reg + val) <= 32)
3822         reg = reg + val - 1;
3823       else
3824         reg = reg + val - 33;
3825       s3_inst.instruction &= 0x7c1f;
3826       s3_inst.instruction |= (reg << 5);
3827       return;
3828     }
3829 }
3830 
3831 /* Handle lcb/lcw/lce/scb/scw/sce.  */
3832 static void
3833 s3_do_ldst_unalign (char *str)
3834 {
3835   int conflict_reg;
3836 
3837   if (s3_university_version == 1)
3838     {
3839       s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3840       return;
3841     }
3842 
3843   s3_skip_whitespace (str);
3844 
3845   /* lcb/scb [rA]+.  */
3846   if (*str == '[')
3847     {
3848       str++;
3849       s3_skip_whitespace (str);
3850 
3851       if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3852 	return;
3853 
3854       if (*str++ == ']')
3855         {
3856           if (*str++ != '+')
3857             {
3858               s3_inst.error = _("missing +");
3859               return;
3860             }
3861         }
3862       else
3863         {
3864           s3_inst.error = _("missing ]");
3865           return;
3866         }
3867 
3868       if (s3_end_of_line (str) == (int) s3_FAIL)
3869 	return;
3870     }
3871   /* lcw/lce/scb/sce rD, [rA]+.  */
3872   else
3873     {
3874       if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3875           || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3876         {
3877           return;
3878         }
3879 
3880       s3_skip_whitespace (str);
3881       if (*str++ == '[')
3882         {
3883           int reg;
3884 
3885           s3_skip_whitespace (str);
3886           if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3887             {
3888               return;
3889             }
3890 
3891           /* Conflicts can occur on stores as well as loads.  */
3892           conflict_reg = (conflict_reg == reg);
3893           s3_skip_whitespace (str);
3894           if (*str++ == ']')
3895             {
3896               unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
3897 
3898               if (*str++ == '+')
3899                 {
3900                   if (conflict_reg)
3901                     {
3902                       as_warn (_("%s register same as write-back base"),
3903                                ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3904                                 ? _("destination") : _("source")));
3905                     }
3906                 }
3907               else
3908                 {
3909                   s3_inst.error = _("missing +");
3910                   return;
3911                 }
3912 
3913               if (s3_end_of_line (str) == (int) s3_FAIL)
3914 		return;
3915             }
3916           else
3917             {
3918               s3_inst.error = _("missing ]");
3919               return;
3920             }
3921         }
3922       else
3923         {
3924           s3_inst.error = s3_BAD_ARGS;
3925           return;
3926         }
3927     }
3928 }
3929 
3930 /* Handle alw/asw.  */
3931 static void
3932 s3_do_ldst_atomic (char *str)
3933 {
3934   if (s3_university_version == 1)
3935     {
3936       s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3937       return;
3938     }
3939 
3940   s3_skip_whitespace (str);
3941 
3942   if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3943       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3944     {
3945       return;
3946     }
3947   else
3948     {
3949 
3950       s3_skip_whitespace (str);
3951       if (*str++ == '[')
3952         {
3953           int reg;
3954 
3955           s3_skip_whitespace (str);
3956           if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3957             {
3958               return;
3959             }
3960 
3961           s3_skip_whitespace (str);
3962           if (*str++ != ']')
3963             {
3964               s3_inst.error = _("missing ]");
3965               return;
3966             }
3967 
3968           s3_end_of_line (str);
3969         }
3970       else
3971 	s3_inst.error = s3_BAD_ARGS;
3972     }
3973 }
3974 
3975 static void
3976 s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3977 		     struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
3978 		     symbolS *add_symbol)
3979 {
3980   int i;
3981   char *p;
3982   fixS *fixp = NULL;
3983   fixS *cur_fixp = NULL;
3984   long where;
3985   struct s3_score_it inst_main;
3986 
3987   memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
3988 
3989   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
3990   inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
3991   inst_main.type = Insn_PIC;
3992 
3993   for (i = 0; i < var_num; i++)
3994     {
3995       inst_main.relax_size += var_insts[i].size;
3996       var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
3997 						      s3_GET_INSN_CLASS (var_insts[i].type));
3998     }
3999 
4000   /* Check data dependency.  */
4001   s3_handle_dependency (&inst_main);
4002 
4003   /* Start a new frag if frag_now is not empty.  */
4004   if (frag_now_fix () != 0)
4005     {
4006       if (!frag_now->tc_frag_data.is_insn)
4007 	{
4008           frag_wane (frag_now);
4009 	}
4010       frag_new (0);
4011     }
4012   frag_grow (20);
4013 
4014   /* Write fr_fix part.  */
4015   p = frag_more (inst_main.size);
4016   s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4017 
4018   if (inst_main.reloc.type != BFD_RELOC_NONE)
4019     fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4020 			     &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4021 
4022   frag_now->tc_frag_data.fixp = fixp;
4023   cur_fixp = frag_now->tc_frag_data.fixp;
4024 
4025 #ifdef OBJ_ELF
4026   dwarf2_emit_insn (inst_main.size);
4027 #endif
4028 
4029   where = p - frag_now->fr_literal + inst_main.size;
4030   for (i = 0; i < var_num; i++)
4031     {
4032       if (i > 0)
4033         where += var_insts[i - 1].size;
4034 
4035       if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4036         {
4037           fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
4038 				   &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4039 				   var_insts[i].reloc.type);
4040           if (fixp)
4041             {
4042               if (cur_fixp)
4043                 {
4044                   cur_fixp->fx_next = fixp;
4045                   cur_fixp = cur_fixp->fx_next;
4046                 }
4047               else
4048                 {
4049                   frag_now->tc_frag_data.fixp = fixp;
4050                   cur_fixp = frag_now->tc_frag_data.fixp;
4051                 }
4052 	    }
4053         }
4054     }
4055 
4056   p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4057                 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4058 				 0, inst_main.size, 0), add_symbol, 0, NULL);
4059 
4060   /* Write fr_var part.
4061      no calling s3_gen_insn_frag, no fixS will be generated.  */
4062   for (i = 0; i < var_num; i++)
4063     {
4064       s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4065       p += var_insts[i].size;
4066     }
4067   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4068   s3_inst.bwarn = -1;
4069 }
4070 
4071 /* Build a relax frag for la instruction when generating s3_PIC,
4072    external symbol first and local symbol second.  */
4073 static void
4074 s3_build_la_pic (int reg_rd, expressionS exp)
4075 {
4076   symbolS *add_symbol = exp.X_add_symbol;
4077   offsetT add_number = exp.X_add_number;
4078   struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4079   struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4080   int fix_num = 0;
4081   int var_num = 0;
4082   char tmp[s3_MAX_LITERAL_POOL_SIZE];
4083   int r1_bak;
4084 
4085   r1_bak = s3_nor1;
4086   s3_nor1 = 0;
4087 
4088   if (add_number == 0)
4089     {
4090       fix_num = 1;
4091       var_num = 2;
4092 
4093       /* For an external symbol, only one insn is generated;
4094          For a local symbol, two insns are generated.  */
4095       /* Fix part
4096          For an external symbol: lw rD, <sym>($gp)
4097 	 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
4098       sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4099       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4100 	return;
4101 
4102       if (reg_rd == s3_PIC_CALL_REG)
4103         s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4104       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4105 
4106       /* Var part
4107 	 For a local symbol :
4108          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4109 	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4110       s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4111       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4112       sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4113       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4114 	return;
4115 
4116       memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4117       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4118     }
4119   else if (add_number >= -0x8000 && add_number <= 0x7fff)
4120     {
4121       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4122       sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4123       if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4124 	return;
4125 
4126       /* Insn 2  */
4127       fix_num = 1;
4128       var_num = 1;
4129       /* Fix part
4130          For an external symbol: addi rD, <constant> */
4131       sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
4132       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4133 	return;
4134 
4135       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4136 
4137       /* Var part
4138  	 For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
4139       sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd,
4140 	       S_GET_NAME (add_symbol), (int) add_number);
4141       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4142 	return;
4143 
4144       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4145       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4146     }
4147   else
4148     {
4149       int hi = (add_number >> 16) & 0x0000FFFF;
4150       int lo = add_number & 0x0000FFFF;
4151 
4152       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4153       sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4154       if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4155 	return;
4156 
4157       /* Insn 2  */
4158       fix_num = 1;
4159       var_num = 1;
4160       /* Fix part
4161 	 For an external symbol: ldis r1, HI%<constant>  */
4162       sprintf (tmp, "ldis r1, %d", hi);
4163       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4164 	return;
4165 
4166       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4167 
4168       /* Var part
4169 	 For a local symbol: ldis r1, HI%<constant>
4170          but, if lo is out of 16 bit, make hi plus 1  */
4171       if ((lo < -0x8000) || (lo > 0x7fff))
4172 	{
4173 	  hi += 1;
4174 	}
4175       sprintf (tmp, "ldis_pic r1, %d", hi);
4176       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4177 	return;
4178 
4179       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4180       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4181 
4182       /* Insn 3  */
4183       fix_num = 1;
4184       var_num = 1;
4185       /* Fix part
4186 	 For an external symbol: ori r1, LO%<constant>  */
4187       sprintf (tmp, "ori r1, %d", lo);
4188       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4189 	return;
4190 
4191       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4192 
4193       /* Var part
4194   	 For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
4195       sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo);
4196       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4197 	return;
4198 
4199       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4200       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4201 
4202       /* Insn 4: add rD, rD, r1  */
4203       sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4204       if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4205 	return;
4206 
4207       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4208       s3_inst.bwarn = -1;
4209     }
4210 
4211   s3_nor1 = r1_bak;
4212 }
4213 
4214 /* Handle la.  */
4215 static void
4216 s3_do_macro_la_rdi32 (char *str)
4217 {
4218   int reg_rd;
4219 
4220   s3_skip_whitespace (str);
4221   if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4222       || s3_skip_past_comma (&str) == (int) s3_FAIL)
4223     {
4224       return;
4225     }
4226   else
4227     {
4228       /* Save str.  */
4229       char *keep_data = str;
4230       char append_str[s3_MAX_LITERAL_POOL_SIZE];
4231 
4232       /* Check immediate value.  */
4233       if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4234         {
4235           s3_inst.error = _("expression error");
4236           return;
4237         }
4238       else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4239                && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL))
4240         {
4241           s3_inst.error = _("value not in range [0, 0xffffffff]");
4242           return;
4243         }
4244 
4245       /* Reset str.  */
4246       str = keep_data;
4247 
4248       /* la rd, simm16.  */
4249       if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
4250         {
4251           s3_end_of_line (str);
4252           return;
4253         }
4254       /* la rd, imm32 or la rd, label.  */
4255       else
4256         {
4257           s3_SET_INSN_ERROR (NULL);
4258           /* Reset str.  */
4259           str = keep_data;
4260           if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4261               || (s3_end_of_line (str) == (int) s3_FAIL))
4262             {
4263               return;
4264             }
4265           else
4266             {
4267               if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol))
4268                 {
4269                   sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4270                   if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4271 		    return;
4272 
4273                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4274                   if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4275 		    return;
4276 		}
4277 	      else
4278 		{
4279 		  gas_assert (s3_inst.reloc.exp.X_add_symbol);
4280 		  s3_build_la_pic (reg_rd, s3_inst.reloc.exp);
4281 		}
4282 
4283               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4284               s3_inst.bwarn = -1;
4285             }
4286         }
4287     }
4288 }
4289 
4290 /* Handle li.  */
4291 static void
4292 s3_do_macro_li_rdi32 (char *str)
4293 {
4294 
4295   int reg_rd;
4296 
4297   s3_skip_whitespace (str);
4298   if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4299       || s3_skip_past_comma (&str) == (int) s3_FAIL)
4300     {
4301       return;
4302     }
4303   else
4304     {
4305       /* Save str.  */
4306       char *keep_data = str;
4307 
4308       /* Check immediate value.  */
4309       if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4310         {
4311           s3_inst.error = _("expression error");
4312           return;
4313         }
4314       else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL
4315                  && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4316         {
4317           s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4318           return;
4319         }
4320 
4321       /* Reset str.  */
4322       str = keep_data;
4323 
4324       /* li rd, simm16.  */
4325       if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
4326         {
4327           s3_end_of_line (str);
4328           return;
4329         }
4330       /* li rd, imm32.  */
4331       else
4332         {
4333           char append_str[s3_MAX_LITERAL_POOL_SIZE];
4334 
4335           /* Reset str.  */
4336           str = keep_data;
4337 
4338           if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4339               || (s3_end_of_line (str) == (int) s3_FAIL))
4340             {
4341               return;
4342             }
4343           else if (s3_inst.reloc.exp.X_add_symbol)
4344             {
4345               s3_inst.error = _("li rd label isn't correct instruction form");
4346               return;
4347             }
4348           else
4349             {
4350               sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4351 
4352               if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4353 		return;
4354               else
4355                 {
4356                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4357                   if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4358 		    return;
4359 
4360                   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4361                   s3_inst.bwarn = -1;
4362                 }
4363             }
4364         }
4365     }
4366 }
4367 
4368 /* Handle mul/mulu/div/divu/rem/remu.  */
4369 static void
4370 s3_do_macro_mul_rdrsrs (char *str)
4371 {
4372   int reg_rd;
4373   int reg_rs1;
4374   int reg_rs2;
4375   char *backupstr;
4376   char append_str[s3_MAX_LITERAL_POOL_SIZE];
4377 
4378   if (s3_university_version == 1)
4379     as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV);
4380 
4381   strcpy (append_str, str);
4382   backupstr = append_str;
4383   s3_skip_whitespace (backupstr);
4384   if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4385       || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4386       || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL))
4387     {
4388       s3_inst.error = s3_BAD_ARGS;
4389       return;
4390     }
4391 
4392   if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4393     {
4394       /* rem/remu rA, rB is error format.  */
4395       if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0)
4396         {
4397           s3_SET_INSN_ERROR (s3_BAD_ARGS);
4398         }
4399       else
4400         {
4401           s3_SET_INSN_ERROR (NULL);
4402           s3_do_rsrs (str);
4403         }
4404       return;
4405     }
4406   else
4407     {
4408       s3_SET_INSN_ERROR (NULL);
4409       if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4410           || (s3_end_of_line (backupstr) == (int) s3_FAIL))
4411         {
4412           return;
4413         }
4414       else
4415         {
4416           char append_str1[s3_MAX_LITERAL_POOL_SIZE];
4417 
4418           if (strcmp (s3_inst.name, "rem") == 0)
4419             {
4420               sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4421               sprintf (append_str1, "mfceh  r%d", reg_rd);
4422             }
4423           else if (strcmp (s3_inst.name, "remu") == 0)
4424             {
4425               sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4426               sprintf (append_str1, "mfceh  r%d", reg_rd);
4427             }
4428           else
4429             {
4430               sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2);
4431               sprintf (append_str1, "mfcel  r%d", reg_rd);
4432             }
4433 
4434           /* Output mul/mulu or div/divu or rem/remu.  */
4435           if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4436 	    return;
4437 
4438           /* Output mfcel or mfceh.  */
4439           if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL)
4440 	    return;
4441 
4442           /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4443           s3_inst.bwarn = -1;
4444         }
4445     }
4446 }
4447 
4448 static void
4449 s3_exp_macro_ldst_abs (char *str)
4450 {
4451   int reg_rd;
4452   char *backupstr, *tmp;
4453   char append_str[s3_MAX_LITERAL_POOL_SIZE];
4454   char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4455   struct s3_score_it inst_backup;
4456   int r1_bak = 0;
4457 
4458   r1_bak = s3_nor1;
4459   s3_nor1 = 0;
4460   memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
4461 
4462   strcpy (verifystr, str);
4463   backupstr = verifystr;
4464   s3_skip_whitespace (backupstr);
4465   if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4466     return;
4467 
4468   tmp = backupstr;
4469   if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4470     return;
4471 
4472   backupstr = tmp;
4473   sprintf (append_str, "li r1  %s", backupstr);
4474   s3_append_insn (append_str, TRUE);
4475 
4476   memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4477   sprintf (append_str, " r%d, [r1,0]", reg_rd);
4478   s3_do_ldst_insn (append_str);
4479 
4480   s3_nor1 = r1_bak;
4481 }
4482 
4483 /* Handle bcmpeq / bcmpne  */
4484 static void
4485 s3_do_macro_bcmp (char *str)
4486 {
4487   int reg_a , reg_b;
4488   char *keep_data;
4489   size_t keep_data_size;
4490   int i;
4491   struct s3_score_it inst_expand[2];
4492   struct s3_score_it inst_main;
4493 
4494   memset (inst_expand, 0, sizeof inst_expand);
4495   s3_skip_whitespace (str);
4496   if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4497       || s3_skip_past_comma (&str) == (int) s3_FAIL
4498       ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4499       || s3_skip_past_comma (&str) == (int) s3_FAIL)
4500     return;
4501 
4502   keep_data_size = strlen (str) + 1;
4503   keep_data = xmalloc (keep_data_size * 2 + 14);
4504   memcpy (keep_data, str, keep_data_size);
4505 
4506   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4507       ||reg_b == 0
4508       || s3_end_of_line (str) == (int) s3_FAIL)
4509     goto out;
4510   else if (s3_inst.reloc.exp.X_add_symbol == 0)
4511     {
4512       s3_inst.error = _("lacking label  ");
4513       goto out;
4514     }
4515   else
4516     {
4517       char *append_str = keep_data + keep_data_size;
4518       s3_SET_INSN_ERROR (NULL);
4519 
4520       s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
4521       s3_inst.reloc.pc_rel = 1;
4522       bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
4523 
4524       /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
4525       s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1)
4526 	| ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7
4527 	| ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20;
4528 
4529       /* Check and set offset.  */
4530       if (((val & 0xfffffe00) != 0)
4531 	  && ((val & 0xfffffe00) != 0xfffffe00))
4532         {
4533           /* support bcmp --> cmp!+beq (bne) */
4534           if (s3_score_pic == s3_NO_PIC)
4535             {
4536 	      sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
4537 	      if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4538 		goto out;
4539 	      if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4540 		sprintf (append_str, "beq %s", keep_data);
4541 	      else
4542 		sprintf (append_str, "bne %s", keep_data);
4543 	      if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4544 		goto out;
4545 	    }
4546 	  else
4547 	    {
4548 	      gas_assert (s3_inst.reloc.exp.X_add_symbol);
4549 	    }
4550 	  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4551 	  s3_inst.bwarn = -1;
4552 	  goto out;
4553         }
4554       else
4555         {
4556           val >>= 1;
4557           s3_inst.instruction |= (val & 0x1)
4558 	    | (((val >> 1) & 0x7) << 7)
4559 	    | (((val >> 4) & 0x1f) << 20);
4560         }
4561 
4562       /* Backup s3_inst.  */
4563       memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
4564 
4565       if (s3_score_pic == s3_NO_PIC)
4566         {
4567 	  sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
4568 	  if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4569 	    goto out;
4570 	  memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4571 
4572 	  if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4573 	    sprintf (append_str, "beq %s", keep_data);
4574 	  else
4575 	    sprintf (append_str, "bne %s", keep_data);
4576 	  if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4577 	    goto out;
4578 	  memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
4579         }
4580       else
4581         {
4582           gas_assert (s3_inst.reloc.exp.X_add_symbol);
4583         }
4584       inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4585       inst_main.type = Insn_BCMP;
4586 
4587       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4588       inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4589 
4590       for (i = 0; i < 2; i++)
4591         inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
4592                                                           s3_GET_INSN_CLASS (inst_expand[i].type));
4593       /* Check data dependency.  */
4594       s3_handle_dependency (&inst_main);
4595       /* Start a new frag if frag_now is not empty.  */
4596       if (frag_now_fix () != 0)
4597 	{
4598 	  if (!frag_now->tc_frag_data.is_insn)
4599 	    frag_wane (frag_now);
4600 	  frag_new (0);
4601 	}
4602       frag_grow (20);
4603 
4604       /* Write fr_fix part.  */
4605       char *p;
4606       p = frag_more (inst_main.size);
4607       s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4608 
4609       if (inst_main.reloc.type != BFD_RELOC_NONE)
4610 	{
4611 	  s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4612 			    &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4613 	}
4614 #ifdef OBJ_ELF
4615       dwarf2_emit_insn (inst_main.size);
4616 #endif
4617 
4618       /* s3_GP instruction can not do optimization, only can do relax between
4619          1 instruction and 3 instructions.  */
4620       p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4621                     s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4622                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
4623 
4624       /* Write fr_var part.
4625          no calling s3_gen_insn_frag, no fixS will be generated.  */
4626       s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4627       p += inst_expand[0].size;
4628       s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4629       p += inst_expand[1].size;
4630 
4631       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4632       s3_inst.bwarn = -1;
4633     }
4634  out:
4635   free (keep_data);
4636 }
4637 
4638 /* Handle bcmpeqz / bcmpnez  */
4639 static void
4640 s3_do_macro_bcmpz (char *str)
4641 {
4642   int reg_a;
4643   char *keep_data;
4644   size_t keep_data_size;
4645   int i;
4646   struct s3_score_it inst_expand[2];
4647   struct s3_score_it inst_main;
4648 
4649   memset (inst_expand, 0, sizeof inst_expand);
4650   s3_skip_whitespace (str);
4651   if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4652       || s3_skip_past_comma (&str) == (int) s3_FAIL)
4653     return;
4654 
4655   keep_data_size = strlen (str) + 1;
4656   keep_data = xmalloc (keep_data_size * 2 + 13);
4657   memcpy (keep_data, str, keep_data_size);
4658 
4659   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4660       || s3_end_of_line (str) == (int) s3_FAIL)
4661     goto out;
4662   else if (s3_inst.reloc.exp.X_add_symbol == 0)
4663     {
4664       s3_inst.error = _("lacking label  ");
4665       goto out;
4666     }
4667   else
4668     {
4669       char *append_str = keep_data + keep_data_size;
4670       s3_SET_INSN_ERROR (NULL);
4671       s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
4672       s3_inst.reloc.pc_rel = 1;
4673       bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
4674 
4675       /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
4676       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;
4677 
4678       /* Check and set offset.  */
4679       if (((val & 0xfffffe00) != 0)
4680 	  && ((val & 0xfffffe00) != 0xfffffe00))
4681         {
4682           if (s3_score_pic == s3_NO_PIC)
4683             {
4684 	      sprintf (append_str, "cmpi! r%d, 0", reg_a);
4685 	      if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4686 		goto out;
4687 	      if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4688 		sprintf (append_str, "beq %s", keep_data);
4689 	      else
4690 		sprintf (append_str, "bne %s", keep_data);
4691 	      if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4692 		goto out;
4693             }
4694           else
4695             {
4696               gas_assert (s3_inst.reloc.exp.X_add_symbol);
4697             }
4698           /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4699           s3_inst.bwarn = -1;
4700 	  goto out;
4701         }
4702       else
4703         {
4704           val >>= 1;
4705           s3_inst.instruction |= (val & 0x1)
4706 	    | (((val >> 1) & 0x7) << 7)
4707 	    | (((val >> 4) & 0x1f) << 20);
4708         }
4709 
4710       /* Backup s3_inst.  */
4711       memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
4712 
4713       if (s3_score_pic == s3_NO_PIC)
4714         {
4715 	  sprintf (append_str, "cmpi! r%d, 0", reg_a);
4716 	  if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4717 	    goto out;
4718 	  memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4719 	  if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4720 	    sprintf (append_str, "beq %s", keep_data);
4721 	  else
4722 	    sprintf (append_str, "bne %s", keep_data);
4723 	  if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4724 	    goto out;
4725 	  memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
4726         }
4727       else
4728         {
4729           gas_assert (s3_inst.reloc.exp.X_add_symbol);
4730         }
4731       inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4732       inst_main.type = Insn_BCMP;
4733 
4734       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4735       inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4736 
4737       for (i = 0; i < 2; i++)
4738         inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction ,
4739 							  s3_GET_INSN_CLASS (inst_expand[i].type));
4740       /* Check data dependency.  */
4741       s3_handle_dependency (&inst_main);
4742       /* Start a new frag if frag_now is not empty.  */
4743       if (frag_now_fix () != 0)
4744 	{
4745 	  if (!frag_now->tc_frag_data.is_insn)
4746 	    frag_wane (frag_now);
4747 	  frag_new (0);
4748 	}
4749       frag_grow (20);
4750 
4751       /* Write fr_fix part.  */
4752       char *p;
4753       p = frag_more (inst_main.size);
4754       s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4755 
4756       if (inst_main.reloc.type != BFD_RELOC_NONE)
4757 	{
4758 	  s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4759 			    &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4760 	}
4761 #ifdef OBJ_ELF
4762       dwarf2_emit_insn (inst_main.size);
4763 #endif
4764 
4765       /* s3_GP instruction can not do optimization, only can do relax between
4766          1 instruction and 3 instructions.  */
4767       p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4768                     s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4769                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
4770 
4771       /* Write fr_var part.
4772          no calling s3_gen_insn_frag, no fixS will be generated.  */
4773       s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4774       p += inst_expand[0].size;
4775       s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4776       p += inst_expand[1].size;
4777 
4778       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4779       s3_inst.bwarn = -1;
4780     }
4781  out:
4782   free (keep_data);
4783 }
4784 
4785 static int
4786 s3_nopic_need_relax (symbolS * sym, int before_relaxing)
4787 {
4788   if (sym == NULL)
4789     return 0;
4790   else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0)
4791     {
4792       const char *symname;
4793       const char *segname;
4794 
4795       /* Find out whether this symbol can be referenced off the $gp
4796          register.  It can be if it is smaller than the -G size or if
4797          it is in the .sdata or .sbss section.  Certain symbols can
4798          not be referenced off the $gp, although it appears as though
4799          they can.  */
4800       symname = S_GET_NAME (sym);
4801       if (symname != (const char *)NULL
4802           && (strcmp (symname, "eprol") == 0
4803               || strcmp (symname, "etext") == 0
4804               || strcmp (symname, "_gp") == 0
4805               || strcmp (symname, "edata") == 0
4806               || strcmp (symname, "_fbss") == 0
4807               || strcmp (symname, "_fdata") == 0
4808               || strcmp (symname, "_ftext") == 0
4809               || strcmp (symname, "end") == 0
4810               || strcmp (symname, GP_DISP_LABEL) == 0))
4811         {
4812           return 1;
4813         }
4814       else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4815 							      /* We must defer this decision until after the whole file has been read,
4816 								 since there might be a .extern after the first use of this symbol.  */
4817 							      || (before_relaxing
4818 								  && S_GET_VALUE (sym) == 0)
4819 							      || (S_GET_VALUE (sym) != 0
4820 								  && S_GET_VALUE (sym) <= s3_g_switch_value)))
4821         {
4822           return 0;
4823         }
4824 
4825       segname = segment_name (S_GET_SEGMENT (sym));
4826       return (strcmp (segname, ".sdata") != 0
4827 	      && strcmp (segname, ".sbss") != 0
4828 	      && strncmp (segname, ".sdata.", 7) != 0
4829 	      && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4830     }
4831   /* We are not optimizing for the $gp register.  */
4832   else
4833     return 1;
4834 }
4835 
4836 /* Build a relax frag for lw/st instruction when generating s3_PIC,
4837    external symbol first and local symbol second.  */
4838 static void
4839 s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4840 {
4841   symbolS *add_symbol = exp.X_add_symbol;
4842   int add_number = exp.X_add_number;
4843   struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4844   struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4845   int fix_num = 0;
4846   int var_num = 0;
4847   char tmp[s3_MAX_LITERAL_POOL_SIZE];
4848   int r1_bak;
4849 
4850   r1_bak = s3_nor1;
4851   s3_nor1 = 0;
4852 
4853   if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4854     {
4855       fix_num = 1;
4856       var_num = 2;
4857 
4858       /* For an external symbol, two insns are generated;
4859          For a local symbol, three insns are generated.  */
4860       /* Fix part
4861          For an external symbol: lw rD, <sym>($gp)
4862 	 (BFD_RELOC_SCORE_GOT15)  */
4863       sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol));
4864       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4865         return;
4866 
4867       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4868 
4869       /* Var part
4870 	 For a local symbol :
4871          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4872 	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4873       s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4874       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4875       sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol));
4876       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4877         return;
4878 
4879       memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4880       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4881 
4882       /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
4883       sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4884       if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4885         return;
4886 
4887       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4888       s3_inst.bwarn = -1;
4889     }
4890   else
4891     {
4892       s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)");
4893       return;
4894     }
4895 
4896   s3_nor1 = r1_bak;
4897 }
4898 
4899 static void
4900 s3_do_macro_ldst_label (char *str)
4901 {
4902   int i;
4903   int ldst_gp_p = 0;
4904   int reg_rd;
4905   int r1_bak;
4906   char *backup_str;
4907   char *label_str;
4908   char *absolute_value;
4909   char append_str[3][s3_MAX_LITERAL_POOL_SIZE];
4910   char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4911   struct s3_score_it inst_backup;
4912   struct s3_score_it inst_expand[3];
4913   struct s3_score_it inst_main;
4914 
4915   memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
4916   strcpy (verifystr, str);
4917   backup_str = verifystr;
4918 
4919   s3_skip_whitespace (backup_str);
4920   if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4921     return;
4922 
4923   if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL)
4924     return;
4925 
4926   label_str = backup_str;
4927 
4928   /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
4929   if (*backup_str == '[')
4930     {
4931       s3_inst.type = Rd_rvalueRs_preSI12;
4932       s3_do_ldst_insn (str);
4933       return;
4934     }
4935 
4936   /* Ld/st rD, imm.  */
4937   absolute_value = backup_str;
4938   s3_inst.type = Rd_rvalueRs_SI15;
4939 
4940   if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL)
4941     {
4942       s3_inst.error = _("expression error");
4943       return;
4944     }
4945   else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4946            && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL))
4947     {
4948       s3_inst.error = _("value not in range [0, 0x7fffffff]");
4949       return;
4950     }
4951   else if (s3_end_of_line (backup_str) == (int) s3_FAIL)
4952     {
4953       s3_inst.error = _("end on line error");
4954       return;
4955     }
4956   else
4957     {
4958       if (s3_inst.reloc.exp.X_add_symbol == 0)
4959         {
4960           memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4961           s3_exp_macro_ldst_abs (str);
4962           return;
4963         }
4964     }
4965 
4966   /* Ld/st rD, label.  */
4967   s3_inst.type = Rd_rvalueRs_SI15;
4968   backup_str = absolute_value;
4969   if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL)
4970       || (s3_end_of_line (backup_str) == (int) s3_FAIL))
4971     {
4972       return;
4973     }
4974   else
4975     {
4976       if (s3_inst.reloc.exp.X_add_symbol == 0)
4977         {
4978           if (!s3_inst.error)
4979 	    s3_inst.error = s3_BAD_ARGS;
4980 
4981           return;
4982         }
4983 
4984       if (s3_score_pic == s3_PIC)
4985         {
4986           int ldst_idx = 0;
4987           ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
4988           s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp,
4989                              s3_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4990           return;
4991         }
4992       else
4993 	{
4994           if ((s3_inst.reloc.exp.X_add_number <= 0x3fff)
4995 	      && (s3_inst.reloc.exp.X_add_number >= -0x4000)
4996 	      && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1)))
4997 	    {
4998               int ldst_idx = 0;
4999 
5000               /* Assign the real opcode.  */
5001               ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
5002               s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
5003               s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value;
5004               s3_inst.instruction |= reg_rd << 20;
5005               s3_inst.instruction |= s3_GP << 15;
5006               s3_inst.relax_inst = 0x8000;
5007               s3_inst.relax_size = 0;
5008               ldst_gp_p = 1;
5009 	    }
5010 	}
5011     }
5012 
5013   /* Backup s3_inst.  */
5014   memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
5015   r1_bak = s3_nor1;
5016   s3_nor1 = 0;
5017 
5018   /* Determine which instructions should be output.  */
5019   sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
5020   sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
5021   sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
5022 
5023   /* Generate three instructions.
5024      la r1, label
5025      ld/st rd, [r1, 0]  */
5026   for (i = 0; i < 3; i++)
5027     {
5028       if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL)
5029 	return;
5030 
5031       memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it));
5032     }
5033 
5034   if (ldst_gp_p)
5035     {
5036       char *p;
5037 
5038       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
5039       inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
5040 
5041       /* relax lw rd, label -> ldis rs, imm16
5042 	 ori  rd, imm16
5043 	 lw rd, [rs, imm15] or lw! rd, [rs, imm5].  */
5044       if (inst_expand[2].relax_size == 0)
5045         inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
5046       else
5047         inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size;
5048 
5049       inst_main.type = Insn_GP;
5050 
5051       for (i = 0; i < 3; i++)
5052 	inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
5053                                                           s3_GET_INSN_CLASS (inst_expand[i].type));
5054 
5055       /* Check data dependency.  */
5056       s3_handle_dependency (&inst_main);
5057 
5058       /* Start a new frag if frag_now is not empty.  */
5059       if (frag_now_fix () != 0)
5060         {
5061           if (!frag_now->tc_frag_data.is_insn)
5062 	    frag_wane (frag_now);
5063 
5064           frag_new (0);
5065         }
5066       frag_grow (20);
5067 
5068       /* Write fr_fix part.  */
5069       p = frag_more (inst_main.size);
5070       s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
5071 
5072       if (inst_main.reloc.type != BFD_RELOC_NONE)
5073         {
5074           s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
5075 			    &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
5076         }
5077 
5078 #ifdef OBJ_ELF
5079       dwarf2_emit_insn (inst_main.size);
5080 #endif
5081 
5082       /* s3_GP instruction can not do optimization, only can do relax between
5083          1 instruction and 3 instructions.  */
5084       p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
5085                     s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
5086                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
5087 
5088       /* Write fr_var part.
5089          no calling s3_gen_insn_frag, no fixS will be generated.  */
5090       s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
5091       p += inst_expand[0].size;
5092       s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
5093       p += inst_expand[1].size;
5094 
5095       /* relax lw rd, label -> ldis rs, imm16
5096 	 ori  rd, imm16
5097 	 lw rd, [rs, imm15] or lw! rd, [rs, imm5].  */
5098       if (inst_expand[2].relax_size == 0)
5099         s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
5100       else
5101         s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size);
5102     }
5103   else
5104     {
5105       s3_gen_insn_frag (&inst_expand[0], NULL);
5106       s3_gen_insn_frag (&inst_expand[1], NULL);
5107       s3_gen_insn_frag (&inst_expand[2], NULL);
5108     }
5109   s3_nor1 = r1_bak;
5110 
5111   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
5112   s3_inst.bwarn = -1;
5113 }
5114 
5115 static void
5116 s3_do_lw_pic (char *str)
5117 {
5118   int reg_rd;
5119 
5120   s3_skip_whitespace (str);
5121   if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5122       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
5123       || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
5124       || (s3_end_of_line (str) == (int) s3_FAIL))
5125     {
5126       return;
5127     }
5128   else
5129     {
5130       if (s3_inst.reloc.exp.X_add_symbol == 0)
5131         {
5132           if (!s3_inst.error)
5133 	    s3_inst.error = s3_BAD_ARGS;
5134 
5135           return;
5136         }
5137 
5138       s3_inst.instruction |= s3_GP << 15;
5139       s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
5140     }
5141 }
5142 
5143 static void
5144 s3_do_empty (char *str)
5145 {
5146   str = str;
5147   if (s3_university_version == 1)
5148     {
5149       if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004)
5150           || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024)
5151           || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044)
5152           || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064))
5153         {
5154           s3_inst.error = s3_ERR_FOR_SCORE5U_MMU;
5155           return;
5156         }
5157     }
5158   if (s3_end_of_line (str) == (int) s3_FAIL)
5159     return;
5160 
5161   if (s3_inst.relax_inst != 0x8000)
5162     {
5163       if (s3_inst.type == NO_OPD)
5164         {
5165           s3_inst.relax_size = 2;
5166         }
5167       else
5168         {
5169           s3_inst.relax_size = 4;
5170         }
5171     }
5172 }
5173 
5174 static void
5175 s3_do16_int (char *str)
5176 {
5177   s3_skip_whitespace (str);
5178   return;
5179 }
5180 
5181 static void
5182 s3_do_jump (char *str)
5183 {
5184   char *save_in;
5185 
5186   s3_skip_whitespace (str);
5187   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5188       || s3_end_of_line (str) == (int) s3_FAIL)
5189     return;
5190 
5191   if (s3_inst.reloc.exp.X_add_symbol == 0)
5192     {
5193       s3_inst.error = _("lacking label  ");
5194       return;
5195     }
5196 
5197   if (!(s3_inst.reloc.exp.X_add_number >= -16777216
5198 	&& s3_inst.reloc.exp.X_add_number <= 16777215))
5199     {
5200       s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
5201       return;
5202     }
5203 
5204   save_in = input_line_pointer;
5205   input_line_pointer = str;
5206   s3_inst.reloc.type = BFD_RELOC_SCORE_JMP;
5207   s3_inst.reloc.pc_rel = 1;
5208   input_line_pointer = save_in;
5209 }
5210 
5211 static void
5212 s3_do_branch (char *str)
5213 {
5214   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5215       || s3_end_of_line (str) == (int) s3_FAIL)
5216     {
5217       return;
5218     }
5219   else if (s3_inst.reloc.exp.X_add_symbol == 0)
5220     {
5221       s3_inst.error = _("lacking label  ");
5222       return;
5223     }
5224   else if (!(s3_inst.reloc.exp.X_add_number >= -524288
5225 	     && s3_inst.reloc.exp.X_add_number <= 524287))
5226     {
5227       s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19-1");
5228       return;
5229     }
5230 
5231   s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5232   s3_inst.reloc.pc_rel = 1;
5233 
5234   /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
5235   s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5236 
5237   /* Compute 16 bit branch instruction.  */
5238   if ((s3_inst.relax_inst != 0x8000)
5239       && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511))
5240     {
5241       s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */
5242       s3_inst.relax_size = 2;
5243     }
5244   else
5245     {
5246       s3_inst.relax_inst = 0x8000;
5247     }
5248 }
5249 
5250 static void
5251 s3_do16_branch (char *str)
5252 {
5253   if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5254        || s3_end_of_line (str) == (int) s3_FAIL))
5255     {
5256       ;
5257     }
5258   else if (s3_inst.reloc.exp.X_add_symbol == 0)
5259     {
5260       s3_inst.error = _("lacking label");
5261     }
5262   else if (!(s3_inst.reloc.exp.X_add_number >= -512
5263 	     && s3_inst.reloc.exp.X_add_number <= 511))
5264     {
5265       s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5266     }
5267   else
5268     {
5269       s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5270       s3_inst.reloc.pc_rel = 1;
5271       s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);
5272       s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff);
5273       s3_inst.relax_size = 4;
5274     }
5275 }
5276 
5277 /* Return true if the given symbol should be considered local for s3_PIC.  */
5278 static bfd_boolean
5279 s3_pic_need_relax (symbolS *sym, asection *segtype)
5280 {
5281   asection *symsec;
5282   bfd_boolean linkonce;
5283 
5284   /* Handle the case of a symbol equated to another symbol.  */
5285   while (symbol_equated_reloc_p (sym))
5286     {
5287       symbolS *n;
5288 
5289       /* It's possible to get a loop here in a badly written
5290 	 program.  */
5291       n = symbol_get_value_expression (sym)->X_add_symbol;
5292       if (n == sym)
5293 	break;
5294       sym = n;
5295     }
5296 
5297   symsec = S_GET_SEGMENT (sym);
5298 
5299   /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5300   linkonce = FALSE;
5301   if (symsec != segtype && ! S_IS_LOCAL (sym))
5302     {
5303       if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0)
5304 	linkonce = TRUE;
5305 
5306       /* The GNU toolchain uses an extension for ELF: a section
5307 	 beginning with the magic string .gnu.linkonce is a linkonce
5308 	 section.  */
5309       if (strncmp (segment_name (symsec), ".gnu.linkonce",
5310 		   sizeof ".gnu.linkonce" - 1) == 0)
5311 	linkonce = TRUE;
5312     }
5313 
5314   /* This must duplicate the test in adjust_reloc_syms.  */
5315   return (!bfd_is_und_section (symsec)
5316 	  && !bfd_is_abs_section (symsec)
5317 	  && !bfd_is_com_section (symsec)
5318 	  && !linkonce
5319 #ifdef OBJ_ELF
5320 	  /* A global or weak symbol is treated as external.  */
5321 	  && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5322 	      || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5323 #endif
5324 	  );
5325 }
5326 
5327 static void
5328 s3_parse_pce_inst (char *insnstr)
5329 {
5330   char c;
5331   char *p;
5332   char first[s3_MAX_LITERAL_POOL_SIZE];
5333   char second[s3_MAX_LITERAL_POOL_SIZE];
5334   struct s3_score_it pec_part_1;
5335 
5336   /* Get first part string of PCE.  */
5337   p = strstr (insnstr, "||");
5338   c = *p;
5339   *p = '\0';
5340   sprintf (first, "%s", insnstr);
5341 
5342   /* Get second part string of PCE.  */
5343   *p = c;
5344   p += 2;
5345   sprintf (second, "%s", p);
5346 
5347   s3_parse_16_32_inst (first, FALSE);
5348   if (s3_inst.error)
5349     return;
5350 
5351   memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst));
5352 
5353   s3_parse_16_32_inst (second, FALSE);
5354   if (s3_inst.error)
5355     return;
5356 
5357   if (   ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE))
5358 	 || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE))
5359 	 || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE)))
5360     {
5361       s3_inst.error = _("pce instruction error (16 bit || 16 bit).");
5362       sprintf (s3_inst.str, "%s", insnstr);
5363       return;
5364     }
5365 
5366   if (!s3_inst.error)
5367     s3_gen_insn_frag (&pec_part_1, &s3_inst);
5368 }
5369 
5370 /* s3: dsp.  */
5371 static void
5372 s3_do16_dsp (char *str)
5373 {
5374   int rd = 0;
5375 
5376   /* Check 3d.  */
5377   if (s3_score3d == 0)
5378     {
5379       s3_inst.error = _("score3d instruction.");
5380       return;
5381     }
5382 
5383   s3_skip_whitespace (str);
5384 
5385   if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL
5386       || s3_end_of_line (str) == (int) s3_FAIL)
5387     {
5388       return;
5389     }
5390   else
5391     {
5392       s3_inst.relax_inst |= rd << 20;
5393       s3_inst.relax_size = 4;
5394     }
5395 }
5396 
5397 static void
5398 s3_do16_dsp2 (char *str)
5399 {
5400   /* Check 3d.  */
5401   if (s3_score3d == 0)
5402     {
5403       s3_inst.error = _("score3d instruction.");
5404       return;
5405     }
5406 
5407   s3_skip_whitespace (str);
5408 
5409   if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
5410       || s3_skip_past_comma (&str) == (int) s3_FAIL
5411       || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
5412       || s3_end_of_line (str) == (int) s3_FAIL)
5413     {
5414       return;
5415     }
5416   else
5417     {
5418       s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20)
5419         | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10);
5420       s3_inst.relax_size = 4;
5421     }
5422 }
5423 
5424 static void
5425 s3_do_dsp (char *str)
5426 {
5427   /* Check 3d.  */
5428   if (s3_score3d == 0)
5429     {
5430       s3_inst.error = _("score3d instruction.");
5431       return;
5432     }
5433 
5434   s3_skip_whitespace (str);
5435 
5436   if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5437       || s3_skip_past_comma (&str) == (int) s3_FAIL
5438       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5439       || s3_end_of_line (str) == (int) s3_FAIL)
5440     return;
5441 
5442   if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
5443     {
5444       s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5445       s3_inst.relax_size = 2;
5446     }
5447   else
5448     s3_inst.relax_inst = 0x8000;
5449 }
5450 
5451 static void
5452 s3_do_dsp2 (char *str)
5453 {
5454   int reg;
5455 
5456   /* Check 3d.  */
5457   if (s3_score3d == 0)
5458     {
5459       s3_inst.error = _("score3d instruction.");
5460       return;
5461     }
5462 
5463   s3_skip_whitespace (str);
5464 
5465   if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5466       || s3_skip_past_comma (&str) == (int) s3_FAIL
5467       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5468       || s3_skip_past_comma (&str) == (int) s3_FAIL
5469       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5470       || s3_end_of_line (str) == (int) s3_FAIL)
5471     {
5472       return;
5473     }
5474   else
5475     {
5476       /* Check mulr, mulur rd is even number.  */
5477       if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
5478 	   || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
5479           && (reg % 2))
5480         {
5481           s3_inst.error = _("rd must be even number.");
5482           return;
5483         }
5484 
5485       if ((((s3_inst.instruction >> 15) & 0x10) == 0)
5486           && (((s3_inst.instruction >> 10) & 0x10) == 0)
5487           && (((s3_inst.instruction >> 20) & 0x10) == 0)
5488           && (s3_inst.relax_inst != 0x8000)
5489           && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
5490         {
5491           s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
5492             | (((s3_inst.instruction >> 15) & 0xf) << 4);
5493           s3_inst.relax_size = 2;
5494         }
5495       else
5496         {
5497           s3_inst.relax_inst = 0x8000;
5498         }
5499     }
5500 }
5501 
5502 static void
5503 s3_do_dsp3 (char *str)
5504 {
5505   /* Check 3d.  */
5506   if (s3_score3d == 0)
5507     {
5508       s3_inst.error = _("score3d instruction.");
5509       return;
5510     }
5511 
5512   s3_skip_whitespace (str);
5513 
5514   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5515       || s3_skip_past_comma (&str) == (int) s3_FAIL
5516       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5517       || s3_end_of_line (str) == (int) s3_FAIL)
5518     return;
5519 
5520   if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
5521     {
5522       s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5523       s3_inst.relax_size = 2;
5524     }
5525   else
5526     s3_inst.relax_inst = 0x8000;
5527 }
5528 
5529 
5530 /* If we change section we must dump the literal pool first.  */
5531 static void
5532 s3_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5533 {
5534   subseg_set (bss_section, (subsegT) get_absolute_expression ());
5535   demand_empty_rest_of_line ();
5536 }
5537 
5538 static void
5539 s3_s_score_text (int ignore)
5540 {
5541   obj_elf_text (ignore);
5542   record_alignment (now_seg, 2);
5543 }
5544 
5545 static void
5546 s3_score_s_section (int ignore)
5547 {
5548   obj_elf_section (ignore);
5549   if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5550     record_alignment (now_seg, 2);
5551 
5552 }
5553 
5554 static void
5555 s3_s_change_sec (int sec)
5556 {
5557   segT seg;
5558 
5559 #ifdef OBJ_ELF
5560   /* The ELF backend needs to know that we are changing sections, so
5561      that .previous works correctly.  We could do something like check
5562      for an obj_section_change_hook macro, but that might be confusing
5563      as it would not be appropriate to use it in the section changing
5564      functions in read.c, since obj-elf.c intercepts those.  FIXME:
5565      This should be cleaner, somehow.  */
5566   obj_elf_section_change_hook ();
5567 #endif
5568   switch (sec)
5569     {
5570     case 'r':
5571       seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5572       bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5573       if (strcmp (TARGET_OS, "elf") != 0)
5574         record_alignment (seg, 4);
5575       demand_empty_rest_of_line ();
5576       break;
5577     case 's':
5578       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5579       bfd_set_section_flags (seg, SEC_ALLOC | SEC_LOAD | 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     }
5585 }
5586 
5587 static void
5588 s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5589 {
5590   long mask, off;
5591 
5592   if (s3_cur_proc_ptr == (s3_procS *) NULL)
5593     {
5594       as_warn (_(".mask outside of .ent"));
5595       demand_empty_rest_of_line ();
5596       return;
5597     }
5598   if (get_absolute_expression_and_terminator (&mask) != ',')
5599     {
5600       as_warn (_("Bad .mask directive"));
5601       --input_line_pointer;
5602       demand_empty_rest_of_line ();
5603       return;
5604     }
5605   off = get_absolute_expression ();
5606   s3_cur_proc_ptr->reg_mask = mask;
5607   s3_cur_proc_ptr->reg_offset = off;
5608   demand_empty_rest_of_line ();
5609 }
5610 
5611 static symbolS *
5612 s3_get_symbol (void)
5613 {
5614   int c;
5615   char *name;
5616   symbolS *p;
5617 
5618   c = get_symbol_name (&name);
5619   p = (symbolS *) symbol_find_or_make (name);
5620   (void) restore_line_pointer (c);
5621   return p;
5622 }
5623 
5624 static long
5625 s3_get_number (void)
5626 {
5627   int negative = 0;
5628   long val = 0;
5629 
5630   if (*input_line_pointer == '-')
5631     {
5632       ++input_line_pointer;
5633       negative = 1;
5634     }
5635   if (!ISDIGIT (*input_line_pointer))
5636     as_bad (_("expected simple number"));
5637   if (input_line_pointer[0] == '0')
5638     {
5639       if (input_line_pointer[1] == 'x')
5640         {
5641           input_line_pointer += 2;
5642           while (ISXDIGIT (*input_line_pointer))
5643             {
5644               val <<= 4;
5645               val |= hex_value (*input_line_pointer++);
5646             }
5647           return negative ? -val : val;
5648         }
5649       else
5650         {
5651           ++input_line_pointer;
5652           while (ISDIGIT (*input_line_pointer))
5653             {
5654               val <<= 3;
5655               val |= *input_line_pointer++ - '0';
5656             }
5657           return negative ? -val : val;
5658         }
5659     }
5660   if (!ISDIGIT (*input_line_pointer))
5661     {
5662       printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5663       as_warn (_("invalid number"));
5664       return -1;
5665     }
5666   while (ISDIGIT (*input_line_pointer))
5667     {
5668       val *= 10;
5669       val += *input_line_pointer++ - '0';
5670     }
5671   return negative ? -val : val;
5672 }
5673 
5674 /* The .aent and .ent directives.  */
5675 static void
5676 s3_s_score_ent (int aent)
5677 {
5678   symbolS *symbolP;
5679   int maybe_text;
5680 
5681   symbolP = s3_get_symbol ();
5682   if (*input_line_pointer == ',')
5683     ++input_line_pointer;
5684   SKIP_WHITESPACE ();
5685   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5686     s3_get_number ();
5687 
5688 #ifdef BFD_ASSEMBLER
5689   if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5690     maybe_text = 1;
5691   else
5692     maybe_text = 0;
5693 #else
5694   if (now_seg != data_section && now_seg != bss_section)
5695     maybe_text = 1;
5696   else
5697     maybe_text = 0;
5698 #endif
5699   if (!maybe_text)
5700     as_warn (_(".ent or .aent not in text section."));
5701   if (!aent && s3_cur_proc_ptr)
5702     as_warn (_("missing .end"));
5703   if (!aent)
5704     {
5705       s3_cur_proc_ptr = &s3_cur_proc;
5706       s3_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5707       s3_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5708       s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5709       s3_cur_proc_ptr->leaf = 0xdeafbeaf;
5710       s3_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5711       s3_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5712       s3_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5713       s3_cur_proc_ptr->isym = symbolP;
5714       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5715       ++s3_numprocs;
5716       if (debug_type == DEBUG_STABS)
5717         stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5718     }
5719   demand_empty_rest_of_line ();
5720 }
5721 
5722 static void
5723 s3_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5724 {
5725   char *backupstr;
5726   char str[30];
5727   long val;
5728   int i = 0;
5729 
5730   backupstr = input_line_pointer;
5731 
5732 #ifdef OBJ_ELF
5733   if (s3_cur_proc_ptr == (s3_procS *) NULL)
5734     {
5735       as_warn (_(".frame outside of .ent"));
5736       demand_empty_rest_of_line ();
5737       return;
5738     }
5739   s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5740   SKIP_WHITESPACE ();
5741   s3_skip_past_comma (&backupstr);
5742   while (*backupstr != ',')
5743     {
5744       str[i] = *backupstr;
5745       i++;
5746       backupstr++;
5747     }
5748   str[i] = '\0';
5749   val = atoi (str);
5750 
5751   SKIP_WHITESPACE ();
5752   s3_skip_past_comma (&backupstr);
5753   s3_cur_proc_ptr->frame_offset = val;
5754   s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5755 
5756   SKIP_WHITESPACE ();
5757   s3_skip_past_comma (&backupstr);
5758   i = 0;
5759   while (*backupstr != '\n')
5760     {
5761       str[i] = *backupstr;
5762       i++;
5763       backupstr++;
5764     }
5765   str[i] = '\0';
5766   val = atoi (str);
5767   s3_cur_proc_ptr->leaf = val;
5768   SKIP_WHITESPACE ();
5769   s3_skip_past_comma (&backupstr);
5770 
5771 #endif /* OBJ_ELF */
5772   while (input_line_pointer != backupstr)
5773     input_line_pointer++;
5774 }
5775 
5776 /* The .end directive.  */
5777 static void
5778 s3_s_score_end (int x ATTRIBUTE_UNUSED)
5779 {
5780   symbolS *p;
5781   int maybe_text;
5782 
5783   /* Generate a .pdr section.  */
5784   segT saved_seg = now_seg;
5785   subsegT saved_subseg = now_subseg;
5786   expressionS exp;
5787   char *fragp;
5788 
5789   if (!is_end_of_line[(unsigned char)*input_line_pointer])
5790     {
5791       p = s3_get_symbol ();
5792       demand_empty_rest_of_line ();
5793     }
5794   else
5795     p = NULL;
5796 
5797 #ifdef BFD_ASSEMBLER
5798   if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5799     maybe_text = 1;
5800   else
5801     maybe_text = 0;
5802 #else
5803   if (now_seg != data_section && now_seg != bss_section)
5804     maybe_text = 1;
5805   else
5806     maybe_text = 0;
5807 #endif
5808 
5809   if (!maybe_text)
5810     as_warn (_(".end not in text section"));
5811   if (!s3_cur_proc_ptr)
5812     {
5813       as_warn (_(".end directive without a preceding .ent directive."));
5814       demand_empty_rest_of_line ();
5815       return;
5816     }
5817   if (p != NULL)
5818     {
5819       gas_assert (S_GET_NAME (p));
5820       if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym)))
5821         as_warn (_(".end symbol does not match .ent symbol."));
5822       if (debug_type == DEBUG_STABS)
5823         stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5824     }
5825   else
5826     as_warn (_(".end directive missing or unknown symbol"));
5827 
5828   if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5829       (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5830       (s3_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5831       (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5832       (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5833 
5834   else
5835     {
5836       (void) frag_now_fix ();
5837       gas_assert (s3_pdr_seg);
5838       subseg_set (s3_pdr_seg, 0);
5839       /* Write the symbol.  */
5840       exp.X_op = O_symbol;
5841       exp.X_add_symbol = p;
5842       exp.X_add_number = 0;
5843       emit_expr (&exp, 4);
5844       fragp = frag_more (7 * 4);
5845       md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4);
5846       md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4);
5847       md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4);
5848       md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4);
5849       md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4);
5850       md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4);
5851       md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4);
5852       subseg_set (saved_seg, saved_subseg);
5853 
5854     }
5855   s3_cur_proc_ptr = NULL;
5856 }
5857 
5858 /* Handle the .set pseudo-op.  */
5859 static void
5860 s3_s_score_set (int x ATTRIBUTE_UNUSED)
5861 {
5862   int i = 0;
5863   char name[s3_MAX_LITERAL_POOL_SIZE];
5864   char * orig_ilp = input_line_pointer;
5865 
5866   while (!is_end_of_line[(unsigned char)*input_line_pointer])
5867     {
5868       name[i] = (char) * input_line_pointer;
5869       i++;
5870       ++input_line_pointer;
5871     }
5872 
5873   name[i] = '\0';
5874 
5875   if (strcmp (name, "nwarn") == 0)
5876     {
5877       s3_warn_fix_data_dependency = 0;
5878     }
5879   else if (strcmp (name, "fixdd") == 0)
5880     {
5881       s3_fix_data_dependency = 1;
5882     }
5883   else if (strcmp (name, "nofixdd") == 0)
5884     {
5885       s3_fix_data_dependency = 0;
5886     }
5887   else if (strcmp (name, "r1") == 0)
5888     {
5889       s3_nor1 = 0;
5890     }
5891   else if (strcmp (name, "nor1") == 0)
5892     {
5893       s3_nor1 = 1;
5894     }
5895   else if (strcmp (name, "optimize") == 0)
5896     {
5897       s3_g_opt = 1;
5898     }
5899   else if (strcmp (name, "volatile") == 0)
5900     {
5901       s3_g_opt = 0;
5902     }
5903   else if (strcmp (name, "pic") == 0)
5904     {
5905       s3_score_pic = s3_PIC;
5906     }
5907   else
5908     {
5909       input_line_pointer = orig_ilp;
5910       s_set (0);
5911     }
5912 }
5913 
5914 /* Handle the .cpload pseudo-op.  This is used when generating s3_PIC code.  It sets the
5915    $gp register for the function based on the function address, which is in the register
5916    named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5917    specially by the linker.  The result is:
5918    ldis gp, %hi(GP_DISP_LABEL)
5919    ori  gp, %low(GP_DISP_LABEL)
5920    add  gp, gp, .cpload argument
5921    The .cpload argument is normally r29.  */
5922 static void
5923 s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5924 {
5925   int reg;
5926   char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5927 
5928   /* If we are not generating s3_PIC code, .cpload is ignored.  */
5929   if (s3_score_pic == s3_NO_PIC)
5930     {
5931       s_ignore (0);
5932       return;
5933     }
5934 
5935   if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5936     return;
5937 
5938   demand_empty_rest_of_line ();
5939 
5940   sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL);
5941   if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5942     return;
5943 
5944   sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL);
5945   if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5946     return;
5947 
5948   sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg);
5949   if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5950     return;
5951 }
5952 
5953 /* Handle the .cprestore pseudo-op.  This stores $gp into a given
5954    offset from $sp.  The offset is remembered, and after making a s3_PIC
5955    call $gp is restored from that location.  */
5956 static void
5957 s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5958 {
5959   int reg;
5960   int cprestore_offset;
5961   char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5962 
5963   /* If we are not generating s3_PIC code, .cprestore is ignored.  */
5964   if (s3_score_pic == s3_NO_PIC)
5965     {
5966       s_ignore (0);
5967       return;
5968     }
5969 
5970   if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5971       || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL)
5972     {
5973       return;
5974     }
5975 
5976   cprestore_offset = get_absolute_expression ();
5977 
5978   if (cprestore_offset <= 0x3fff)
5979     {
5980       sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset);
5981       if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5982         return;
5983     }
5984   else
5985     {
5986       int r1_bak;
5987 
5988       r1_bak = s3_nor1;
5989       s3_nor1 = 0;
5990 
5991       sprintf (insn_str, "li r1, %d", cprestore_offset);
5992       if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5993         return;
5994 
5995       sprintf (insn_str, "add r1, r1, r%d", reg);
5996       if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5997         return;
5998 
5999       sprintf (insn_str, "sw r%d, [r1]", s3_GP);
6000       if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6001         return;
6002 
6003       s3_nor1 = r1_bak;
6004     }
6005 
6006   demand_empty_rest_of_line ();
6007 }
6008 
6009 /* Handle the .gpword pseudo-op.  This is used when generating s3_PIC
6010    code.  It generates a 32 bit s3_GP relative reloc.  */
6011 static void
6012 s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6013 {
6014   expressionS ex;
6015   char *p;
6016 
6017   /* When not generating s3_PIC code, this is treated as .word.  */
6018   if (s3_score_pic == s3_NO_PIC)
6019     {
6020       cons (4);
6021       return;
6022     }
6023   expression (&ex);
6024   if (ex.X_op != O_symbol || ex.X_add_number != 0)
6025     {
6026       as_bad (_("Unsupported use of .gpword"));
6027       ignore_rest_of_line ();
6028     }
6029   p = frag_more (4);
6030   s3_md_number_to_chars (p, (valueT) 0, 4);
6031   fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6032   demand_empty_rest_of_line ();
6033 }
6034 
6035 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
6036    tables in s3_PIC code.  */
6037 static void
6038 s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6039 {
6040   int reg;
6041   char insn_str[s3_MAX_LITERAL_POOL_SIZE];
6042 
6043   /* If we are not generating s3_PIC code, .cpload is ignored.  */
6044   if (s3_score_pic == s3_NO_PIC)
6045     {
6046       s_ignore (0);
6047       return;
6048     }
6049 
6050   if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
6051     {
6052       return;
6053     }
6054   demand_empty_rest_of_line ();
6055 
6056   /* Add $gp to the register named as an argument.  */
6057   sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP);
6058   if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6059     return;
6060 }
6061 
6062 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6063 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)	\
6064   do							\
6065     {							\
6066       if ((SIZE) >= 8)					\
6067 	(P2VAR) = 3;					\
6068       else if ((SIZE) >= 4)				\
6069 	(P2VAR) = 2;					\
6070       else if ((SIZE) >= 2)				\
6071 	(P2VAR) = 1;					\
6072       else						\
6073 	(P2VAR) = 0;					\
6074     }							\
6075   while (0)
6076 #endif
6077 
6078 static void
6079 s3_s_score_lcomm (int bytes_p)
6080 {
6081   char *name;
6082   char c;
6083   char *p;
6084   int temp;
6085   symbolS *symbolP;
6086   segT current_seg = now_seg;
6087   subsegT current_subseg = now_subseg;
6088   const int max_alignment = 15;
6089   int align = 0;
6090   segT bss_seg = bss_section;
6091   int needs_align = 0;
6092 
6093   c = get_symbol_name (&name);
6094   p = input_line_pointer;
6095   (void) restore_line_pointer (c);
6096 
6097   if (name == p)
6098     {
6099       as_bad (_("expected symbol name"));
6100       discard_rest_of_line ();
6101       return;
6102     }
6103 
6104   SKIP_WHITESPACE ();
6105 
6106   /* Accept an optional comma after the name.  The comma used to be
6107      required, but Irix 5 cc does not generate it.  */
6108   if (*input_line_pointer == ',')
6109     {
6110       ++input_line_pointer;
6111       SKIP_WHITESPACE ();
6112     }
6113 
6114   if (is_end_of_line[(unsigned char)*input_line_pointer])
6115     {
6116       as_bad (_("missing size expression"));
6117       return;
6118     }
6119 
6120   if ((temp = get_absolute_expression ()) < 0)
6121     {
6122       as_warn (_("BSS length (%d) < 0 ignored"), temp);
6123       ignore_rest_of_line ();
6124       return;
6125     }
6126 
6127 #if defined (TC_SCORE)
6128   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6129     {
6130       /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
6131       if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6132 	{
6133 	  bss_seg = subseg_new (".sbss", 1);
6134 	  seg_info (bss_seg)->bss = 1;
6135 #ifdef BFD_ASSEMBLER
6136 	  if (!bfd_set_section_flags (bss_seg, SEC_ALLOC))
6137 	    as_warn (_("error setting flags for \".sbss\": %s"),
6138 		     bfd_errmsg (bfd_get_error ()));
6139 #endif
6140 	}
6141     }
6142 #endif
6143 
6144   SKIP_WHITESPACE ();
6145   if (*input_line_pointer == ',')
6146     {
6147       ++input_line_pointer;
6148       SKIP_WHITESPACE ();
6149 
6150       if (is_end_of_line[(unsigned char)*input_line_pointer])
6151         {
6152           as_bad (_("missing alignment"));
6153           return;
6154         }
6155       else
6156         {
6157           align = get_absolute_expression ();
6158           needs_align = 1;
6159         }
6160     }
6161 
6162   if (!needs_align)
6163     {
6164       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6165 
6166       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6167       if (align)
6168         record_alignment (bss_seg, align);
6169     }
6170 
6171   if (needs_align)
6172     {
6173       if (bytes_p)
6174         {
6175           /* Convert to a power of 2.  */
6176           if (align != 0)
6177             {
6178               unsigned int i;
6179 
6180               for (i = 0; align != 0; align >>= 1, ++i)
6181                 ;
6182               align = i - 1;
6183             }
6184         }
6185 
6186       if (align > max_alignment)
6187         {
6188           align = max_alignment;
6189           as_warn (_("alignment too large; %d assumed"), align);
6190         }
6191       else if (align < 0)
6192         {
6193           align = 0;
6194           as_warn (_("alignment negative; 0 assumed"));
6195         }
6196 
6197       record_alignment (bss_seg, align);
6198     }
6199   else
6200     {
6201       /* Assume some objects may require alignment on some systems.  */
6202 #if defined (TC_ALPHA) && ! defined (VMS)
6203       if (temp > 1)
6204         {
6205           align = ffs (temp) - 1;
6206           if (temp % (1 << align))
6207             abort ();
6208         }
6209 #endif
6210     }
6211 
6212   *p = 0;
6213   symbolP = symbol_find_or_make (name);
6214   *p = c;
6215 
6216   if (
6217 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
6218 #ifdef BFD_ASSEMBLER
6219       (OUTPUT_FLAVOR != bfd_target_aout_flavour
6220        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6221 #else
6222       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6223 #endif
6224 #endif
6225       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6226     {
6227       char *pfrag;
6228 
6229       subseg_set (bss_seg, 1);
6230 
6231       if (align)
6232         frag_align (align, 0, 0);
6233 
6234       /* Detach from old frag.  */
6235       if (S_GET_SEGMENT (symbolP) == bss_seg)
6236         symbol_get_frag (symbolP)->fr_symbol = NULL;
6237 
6238       symbol_set_frag (symbolP, frag_now);
6239       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6240       *pfrag = 0;
6241 
6242 
6243       S_SET_SEGMENT (symbolP, bss_seg);
6244 
6245 #ifdef OBJ_COFF
6246       /* The symbol may already have been created with a preceding
6247          ".globl" directive -- be careful not to step on storage class
6248          in that case.  Otherwise, set it to static.  */
6249       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6250         {
6251           S_SET_STORAGE_CLASS (symbolP, C_STAT);
6252         }
6253 #endif /* OBJ_COFF */
6254 
6255 #ifdef S_SET_SIZE
6256       S_SET_SIZE (symbolP, temp);
6257 #endif
6258     }
6259   else
6260     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6261 
6262   subseg_set (current_seg, current_subseg);
6263 
6264   demand_empty_rest_of_line ();
6265 }
6266 
6267 static void
6268 s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab)
6269 {
6270   int i = 0;
6271   int len = strlen (r->name) + 2;
6272   char *buf = XNEWVEC (char, len);
6273   char *buf2 = XNEWVEC (char, len);
6274 
6275   strcpy (buf + i, r->name);
6276   for (i = 0; buf[i]; i++)
6277     {
6278       buf2[i] = TOUPPER (buf[i]);
6279     }
6280   buf2[i] = '\0';
6281 
6282   hash_insert (htab, buf, (void *) r);
6283   hash_insert (htab, buf2, (void *) r);
6284 }
6285 
6286 static void
6287 s3_build_reg_hsh (struct s3_reg_map *map)
6288 {
6289   const struct s3_reg_entry *r;
6290 
6291   if ((map->htab = hash_new ()) == NULL)
6292     {
6293       as_fatal (_("virtual memory exhausted"));
6294     }
6295   for (r = map->names; r->name != NULL; r++)
6296     {
6297       s3_insert_reg (r, map->htab);
6298     }
6299 }
6300 
6301 /* Iterate over the base tables to create the instruction patterns.  */
6302 static void
6303 s3_build_score_ops_hsh (void)
6304 {
6305   unsigned int i;
6306   static struct obstack insn_obstack;
6307 
6308   obstack_begin (&insn_obstack, 4000);
6309   for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
6310     {
6311       const struct s3_asm_opcode *insn = s3_score_insns + i;
6312       size_t len = strlen (insn->template_name);
6313       struct s3_asm_opcode *new_opcode;
6314       char *template_name;
6315       new_opcode = (struct s3_asm_opcode *)
6316 	obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
6317       template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
6318 
6319       strcpy (template_name, insn->template_name);
6320       new_opcode->template_name = template_name;
6321       new_opcode->parms = insn->parms;
6322       new_opcode->value = insn->value;
6323       new_opcode->relax_value = insn->relax_value;
6324       new_opcode->type = insn->type;
6325       new_opcode->bitmask = insn->bitmask;
6326       hash_insert (s3_score_ops_hsh, new_opcode->template_name,
6327                    (void *) new_opcode);
6328     }
6329 }
6330 
6331 static void
6332 s3_build_dependency_insn_hsh (void)
6333 {
6334   unsigned int i;
6335   static struct obstack dependency_obstack;
6336 
6337   obstack_begin (&dependency_obstack, 4000);
6338   for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
6339     {
6340       const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
6341       size_t len = strlen (tmp->insn_name);
6342       struct s3_insn_to_dependency *new_i2n;
6343       char *buf;
6344 
6345       new_i2n = (struct s3_insn_to_dependency *)
6346 	obstack_alloc (&dependency_obstack,
6347 		       sizeof (struct s3_insn_to_dependency));
6348       buf = (char *) obstack_alloc (&dependency_obstack, len + 1);
6349 
6350       strcpy (buf, tmp->insn_name);
6351       new_i2n->insn_name = buf;
6352       new_i2n->type = tmp->type;
6353       hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name,
6354                    (void *) new_i2n);
6355     }
6356 }
6357 
6358 static void
6359 s_score_bss (int ignore ATTRIBUTE_UNUSED)
6360 {
6361   if (score3)
6362     return s3_s_score_bss (ignore);
6363   else
6364     return s7_s_score_bss (ignore);
6365 }
6366 
6367 static void
6368 s_score_text (int ignore)
6369 {
6370   if (score3)
6371     return s3_s_score_text (ignore);
6372   else
6373     return s7_s_score_text (ignore);
6374 }
6375 
6376 static void
6377 s_section (int ignore)
6378 {
6379   if (score3)
6380     return s3_score_s_section (ignore);
6381   else
6382     return s7_s_section (ignore);
6383 }
6384 
6385 static void
6386 s_change_sec (int sec)
6387 {
6388   if (score3)
6389     return s3_s_change_sec (sec);
6390   else
6391     return s7_s_change_sec (sec);
6392 }
6393 
6394 static void
6395 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
6396 {
6397   if (score3)
6398     return s3_s_score_mask (reg_type);
6399   else
6400     return s7_s_score_mask (reg_type);
6401 }
6402 
6403 static void
6404 s_score_ent (int aent)
6405 {
6406   if (score3)
6407     return s3_s_score_ent (aent);
6408   else
6409     return s7_s_score_ent (aent);
6410 }
6411 
6412 static void
6413 s_score_frame (int ignore ATTRIBUTE_UNUSED)
6414 {
6415   if (score3)
6416     return s3_s_score_frame (ignore);
6417   else
6418     return s7_s_score_frame (ignore);
6419 }
6420 
6421 static void
6422 s_score_end (int x ATTRIBUTE_UNUSED)
6423 {
6424   if (score3)
6425     return s3_s_score_end (x);
6426   else
6427     return s7_s_score_end (x);
6428 }
6429 
6430 static void
6431 s_score_set (int x ATTRIBUTE_UNUSED)
6432 {
6433   if (score3)
6434     return s3_s_score_set (x);
6435   else
6436     return s7_s_score_set (x);
6437 }
6438 
6439 static void
6440 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6441 {
6442   if (score3)
6443     return s3_s_score_cpload (ignore);
6444   else
6445     return s7_s_score_cpload (ignore);
6446 }
6447 
6448 static void
6449 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6450 {
6451   if (score3)
6452     return s3_s_score_cprestore (ignore);
6453   else
6454     return s7_s_score_cprestore (ignore);
6455 }
6456 
6457 static void
6458 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6459 {
6460   if (score3)
6461     return s3_s_score_gpword (ignore);
6462   else
6463     return s7_s_score_gpword (ignore);
6464 }
6465 
6466 static void
6467 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6468 {
6469   if (score3)
6470     return s3_s_score_cpadd (ignore);
6471   else
6472     return s7_s_score_cpadd (ignore);
6473 }
6474 
6475 static void
6476 s_score_lcomm (int bytes_p)
6477 {
6478   if (score3)
6479     return s3_s_score_lcomm (bytes_p);
6480   else
6481     return s7_s_score_lcomm (bytes_p);
6482 }
6483 
6484 static void
6485 s3_assemble (char *str)
6486 {
6487   know (str);
6488   know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
6489 
6490   memset (&s3_inst, '\0', sizeof (s3_inst));
6491   if (s3_INSN_IS_PCE_P (str))
6492     s3_parse_pce_inst (str);
6493   else if (s3_INSN_IS_48_P (str))
6494     s3_parse_48_inst (str, TRUE);
6495   else
6496     s3_parse_16_32_inst (str, TRUE);
6497 
6498   if (s3_inst.error)
6499     as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
6500 }
6501 
6502 static void
6503 s3_operand (expressionS * exp)
6504 {
6505   if (s3_in_my_get_expression)
6506     {
6507       exp->X_op = O_illegal;
6508       if (s3_inst.error == NULL)
6509         {
6510           s3_inst.error = _("bad expression");
6511         }
6512     }
6513 }
6514 
6515 static void
6516 s3_begin (void)
6517 {
6518   unsigned int i;
6519   segT seg;
6520   subsegT subseg;
6521 
6522   if ((s3_score_ops_hsh = hash_new ()) == NULL)
6523     as_fatal (_("virtual memory exhausted"));
6524 
6525   s3_build_score_ops_hsh ();
6526 
6527   if ((s3_dependency_insn_hsh = hash_new ()) == NULL)
6528     as_fatal (_("virtual memory exhausted"));
6529 
6530   s3_build_dependency_insn_hsh ();
6531 
6532   for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
6533     s3_build_reg_hsh (s3_all_reg_maps + i);
6534 
6535   /* Initialize dependency vector.  */
6536   s3_init_dependency_vector ();
6537 
6538   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6539   seg = now_seg;
6540   subseg = now_subseg;
6541   s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6542   bfd_set_section_flags (s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6543   bfd_set_section_alignment (s3_pdr_seg, 2);
6544   subseg_set (seg, subseg);
6545 
6546   if (s3_USE_GLOBAL_POINTER_OPT)
6547     bfd_set_gp_size (stdoutput, s3_g_switch_value);
6548 }
6549 
6550 static void
6551 s3_number_to_chars (char *buf, valueT val, int n)
6552 {
6553   if (target_big_endian)
6554     number_to_chars_bigendian (buf, val, n);
6555   else
6556     number_to_chars_littleendian (buf, val, n);
6557 }
6558 
6559 static valueT
6560 s3_normal_chars_to_number (char *buf, int n)
6561 {
6562   valueT result = 0;
6563   unsigned char *where = (unsigned char *)buf;
6564 
6565   if (target_big_endian)
6566     {
6567       while (n--)
6568         {
6569           result <<= 8;
6570           result |= (*where++ & 255);
6571         }
6572     }
6573   else
6574     {
6575       while (n--)
6576         {
6577           result <<= 8;
6578           result |= (where[n] & 255);
6579         }
6580     }
6581 
6582   return result;
6583 }
6584 
6585 static void
6586 s3_number_to_chars_littleendian (void *p, valueT data, int n)
6587 {
6588   char *buf = (char *) p;
6589 
6590   switch (n)
6591     {
6592     case 4:
6593       md_number_to_chars (buf, data >> 16, 2);
6594       md_number_to_chars (buf + 2, data, 2);
6595       break;
6596     case 6:
6597       md_number_to_chars (buf, data >> 32, 2);
6598       md_number_to_chars (buf + 2, data >> 16, 2);
6599       md_number_to_chars (buf + 4, data, 2);
6600       break;
6601     default:
6602       /* Error routine.  */
6603       as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6604       break;
6605     }
6606 }
6607 
6608 static valueT
6609 s3_chars_to_number_littleendian (const void *p, int n)
6610 {
6611   char *buf = (char *) p;
6612   valueT result = 0;
6613 
6614   switch (n)
6615     {
6616     case 4:
6617       result =  s3_normal_chars_to_number (buf, 2) << 16;
6618       result |= s3_normal_chars_to_number (buf + 2, 2);
6619       break;
6620     case 6:
6621       result =  s3_normal_chars_to_number (buf, 2) << 32;
6622       result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
6623       result |= s3_normal_chars_to_number (buf + 4, 2);
6624       break;
6625     default:
6626       /* Error routine.  */
6627       as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6628       break;
6629     }
6630 
6631   return result;
6632 }
6633 
6634 static void
6635 s3_md_number_to_chars (char *buf, valueT val, int n)
6636 {
6637   if (!target_big_endian && n >= 4)
6638     s3_number_to_chars_littleendian (buf, val, n);
6639   else
6640     md_number_to_chars (buf, val, n);
6641 }
6642 
6643 static valueT
6644 s3_md_chars_to_number (char *buf, int n)
6645 {
6646   valueT result = 0;
6647 
6648   if (!target_big_endian && n >= 4)
6649     result = s3_chars_to_number_littleendian (buf, n);
6650   else
6651     result = s3_normal_chars_to_number (buf, n);
6652 
6653   return result;
6654 }
6655 
6656 static const char *
6657 s3_atof (int type, char *litP, int *sizeP)
6658 {
6659   int prec;
6660   LITTLENUM_TYPE words[MAX_LITTLENUMS];
6661   char *t;
6662   int i;
6663 
6664   switch (type)
6665     {
6666     case 'f':
6667     case 'F':
6668     case 's':
6669     case 'S':
6670       prec = 2;
6671       break;
6672     case 'd':
6673     case 'D':
6674     case 'r':
6675     case 'R':
6676       prec = 4;
6677       break;
6678     case 'x':
6679     case 'X':
6680     case 'p':
6681     case 'P':
6682       prec = 6;
6683       break;
6684     default:
6685       *sizeP = 0;
6686       return _("bad call to MD_ATOF()");
6687     }
6688 
6689   t = atof_ieee (input_line_pointer, type, words);
6690   if (t)
6691     input_line_pointer = t;
6692   *sizeP = prec * 2;
6693 
6694   if (target_big_endian)
6695     {
6696       for (i = 0; i < prec; i++)
6697         {
6698           s3_md_number_to_chars (litP, (valueT) words[i], 2);
6699           litP += 2;
6700         }
6701     }
6702   else
6703     {
6704       for (i = 0; i < prec; i += 2)
6705         {
6706           s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
6707           s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
6708           litP += 4;
6709         }
6710     }
6711 
6712   return 0;
6713 }
6714 
6715 static void
6716 s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6717 {
6718   know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
6719 }
6720 
6721 static void
6722 s3_validate_fix (fixS *fixP)
6723 {
6724   fixP->fx_where += fixP->fx_frag->insn_addr;
6725 }
6726 
6727 static int
6728 s3_force_relocation (struct fix *fixp)
6729 {
6730   int retval = 0;
6731 
6732   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6733       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6734       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6735       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6736       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6737       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
6738       || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
6739     {
6740       retval = 1;
6741     }
6742   return retval;
6743 }
6744 
6745 static bfd_boolean
6746 s3_fix_adjustable (fixS * fixP)
6747 {
6748   if (fixP->fx_addsy == NULL)
6749     {
6750       return 1;
6751     }
6752   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6753 	   && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6754     {
6755       return 0;
6756     }
6757   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6758            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6759            || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6760            || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6761     {
6762       return 0;
6763     }
6764 
6765   return 1;
6766 }
6767 
6768 static void
6769 s3_elf_final_processing (void)
6770 {
6771   unsigned long val = 0;
6772 
6773   if (score3)
6774     val = E_SCORE_MACH_SCORE3;
6775   else if (score7)
6776     val = E_SCORE_MACH_SCORE7;
6777 
6778   elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6779   elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6780   elf_elfheader (stdoutput)->e_flags |= val;
6781 
6782   if (s3_fix_data_dependency == 1)
6783     {
6784       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6785     }
6786   if (s3_score_pic == s3_PIC)
6787     {
6788       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6789     }
6790 }
6791 
6792 static int
6793 s3_judge_size_before_relax (fragS * fragp, asection *sec)
6794 {
6795   int change = 0;
6796 
6797   if (s3_score_pic == s3_NO_PIC)
6798     change = s3_nopic_need_relax (fragp->fr_symbol, 0);
6799   else
6800     change = s3_pic_need_relax (fragp->fr_symbol, sec);
6801 
6802   if (change == 1)
6803     {
6804       /* Only at the first time determining whether s3_GP instruction relax should be done,
6805          return the difference between instruction size and instruction relax size.  */
6806       if (fragp->fr_opcode == NULL)
6807 	{
6808 	  fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
6809 	  fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6810           return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
6811 	}
6812     }
6813 
6814   return 0;
6815 }
6816 
6817 static int
6818 s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
6819 {
6820   if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6821       || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6822     return s3_judge_size_before_relax (fragp, sec);
6823 
6824   return 0;
6825 }
6826 
6827 static int
6828 s3_relax_branch_inst32 (fragS * fragp)
6829 {
6830   fragp->fr_opcode = NULL;
6831   return 0;
6832 }
6833 
6834 static int
6835 s3_relax_branch_inst16 (fragS * fragp)
6836 {
6837   int relaxable_p = 0;
6838   int frag_addr = fragp->fr_address + fragp->insn_addr;
6839   addressT symbol_address = 0;
6840   symbolS *s;
6841   offsetT offset;
6842   long value;
6843   unsigned long inst_value;
6844 
6845   relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6846 
6847   s = fragp->fr_symbol;
6848   if (s == NULL)
6849     frag_addr = 0;
6850   else
6851     symbol_address = (addressT) symbol_get_frag (s)->fr_address;
6852 
6853   inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
6854   offset = (inst_value & 0x1ff) << 1;
6855   if ((offset & 0x200) == 0x200)
6856     offset |= 0xfffffc00;
6857 
6858   value = offset + symbol_address - frag_addr;
6859 
6860   if (relaxable_p
6861       && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6862       && fragp->fr_fix == 2
6863       && (S_IS_DEFINED (s)
6864           && !S_IS_COMMON (s)
6865           && !S_IS_EXTERNAL (s)))
6866     {
6867       /* Relax branch 32 to branch 16.  */
6868       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6869       fragp->fr_fix = 4;
6870       return 2;
6871     }
6872   else
6873     return 0;
6874 }
6875 
6876 static int
6877 s3_relax_cmpbranch_inst32 (fragS * fragp)
6878 {
6879   int relaxable_p = 0;
6880   symbolS *s;
6881   /* For sign bit.  */
6882   long offset;
6883   long frag_addr = fragp->fr_address + fragp->insn_addr;
6884   long symbol_address = 0;
6885   long value;
6886   unsigned long inst_value;
6887 
6888   relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6889 
6890   s = fragp->fr_symbol;
6891   if (s == NULL)
6892     frag_addr = 0;
6893   else
6894     symbol_address = (addressT) symbol_get_frag (s)->fr_address;
6895 
6896   inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
6897   offset = (inst_value & 0x1)
6898     | (((inst_value >> 7) & 0x7) << 1)
6899     | (((inst_value >> 21) & 0x1f) << 4);
6900   offset <<= 1;
6901   if ((offset & 0x200) == 0x200)
6902     offset |= 0xfffffe00;
6903 
6904   value = offset + symbol_address - frag_addr;
6905   /* change the order of judging rule is because
6906      1.not defined symbol or common symbol or external symbol will change
6907      bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
6908      2.if the flow is as before : it will results to recursive loop
6909   */
6910   if (fragp->fr_fix == 6)
6911     {
6912       /* Have already relaxed!  Just return 0 to terminate the loop.  */
6913       return 0;
6914     }
6915   /* need to translate when extern or not defined or common symbol */
6916   else if ((relaxable_p
6917 	    && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6918 	    && fragp->fr_fix == 4)
6919 	   || !S_IS_DEFINED (s)
6920 	   ||S_IS_COMMON (s)
6921 	   ||S_IS_EXTERNAL (s))
6922     {
6923       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6924       fragp->fr_fix = 6;
6925       return 2;
6926     }
6927   else
6928     {
6929       /* Never relax.  Modify fr_opcode to NULL to verify it's value in
6930          md_apply_fix.  */
6931       fragp->fr_opcode = NULL;
6932       return 0;
6933     }
6934 }
6935 
6936 
6937 static int
6938 s3_relax_other_inst32 (fragS * fragp)
6939 {
6940   int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6941 
6942   if (relaxable_p
6943       && fragp->fr_fix == 4)
6944     {
6945       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6946       fragp->fr_fix = 2;
6947       return -2;
6948     }
6949   else
6950     return 0;
6951 }
6952 
6953 static int
6954 s3_relax_gp_and_pic_inst32 (void)
6955 {
6956   /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
6957      instructions.  We don't change relax size here.  */
6958   return 0;
6959 }
6960 
6961 static int
6962 s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
6963 {
6964   int grows = 0;
6965   int adjust_align_p = 0;
6966 
6967   /* If the instruction address is odd, make it half word align first.  */
6968   if ((fragp->fr_address) % 2 != 0)
6969     {
6970       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6971 	{
6972           fragp->insn_addr = 1;
6973           grows += 1;
6974           adjust_align_p = 1;
6975 	}
6976     }
6977 
6978   switch (s3_RELAX_TYPE (fragp->fr_subtype))
6979     {
6980     case PC_DISP19div2:
6981       grows += s3_relax_branch_inst32 (fragp);
6982       break;
6983 
6984     case PC_DISP8div2:
6985       grows += s3_relax_branch_inst16 (fragp);
6986       break;
6987 
6988     case Insn_BCMP :
6989       grows += s3_relax_cmpbranch_inst32 (fragp);
6990       break;
6991 
6992     case Insn_GP:
6993     case Insn_PIC:
6994       grows += s3_relax_gp_and_pic_inst32 ();
6995       break;
6996 
6997     default:
6998       grows += s3_relax_other_inst32 (fragp);
6999       break;
7000     }
7001 
7002   /* newly added */
7003   if (adjust_align_p && fragp->insn_addr)
7004     {
7005       fragp->fr_fix += fragp->insn_addr;
7006     }
7007 
7008   return grows;
7009 }
7010 
7011 static void
7012 s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7013 {
7014   unsigned int r_old;
7015   unsigned int r_new;
7016   char backup[20];
7017   fixS *fixp;
7018 
7019   r_old = s3_RELAX_OLD (fragp->fr_subtype);
7020   r_new = s3_RELAX_NEW (fragp->fr_subtype);
7021 
7022   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
7023   if (fragp->fr_opcode == NULL)
7024     {
7025       memcpy (backup, fragp->fr_literal, r_old);
7026       fragp->fr_fix = r_old;
7027     }
7028   else
7029     {
7030       memcpy (backup, fragp->fr_literal + r_old, r_new);
7031       fragp->fr_fix = r_new;
7032     }
7033 
7034   fixp = fragp->tc_frag_data.fixp;
7035   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
7036     {
7037       if (fragp->fr_opcode)
7038 	fixp->fx_done = 1;
7039       fixp = fixp->fx_next;
7040     }
7041   while (fixp && fixp->fx_frag == fragp)
7042     {
7043       if (fragp->fr_opcode)
7044 	fixp->fx_where -= r_old + fragp->insn_addr;
7045       else
7046 	fixp->fx_done = 1;
7047       fixp = fixp->fx_next;
7048     }
7049 
7050   if (fragp->insn_addr)
7051     {
7052       s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
7053     }
7054   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
7055   fragp->fr_fix += fragp->insn_addr;
7056 }
7057 
7058 static long
7059 s3_pcrel_from (fixS * fixP)
7060 {
7061   long retval = 0;
7062 
7063   if (fixP->fx_addsy
7064       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
7065       && (fixP->fx_subsy == NULL))
7066     {
7067       retval = 0;
7068     }
7069   else
7070     {
7071       retval = fixP->fx_where + fixP->fx_frag->fr_address;
7072     }
7073 
7074   return retval;
7075 }
7076 
7077 static valueT
7078 s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7079 {
7080   int align = bfd_section_alignment (segment);
7081   return ((size + (1 << align) - 1) & -(1 << align));
7082 }
7083 
7084 static void
7085 s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
7086 {
7087   offsetT value = *valP;
7088   offsetT newval;
7089   offsetT content;
7090   unsigned short HI, LO;
7091 
7092   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
7093 
7094   gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
7095   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
7096     {
7097       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
7098         fixP->fx_done = 1;
7099     }
7100 
7101   /* If this symbol is in a different section then we need to leave it for
7102      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
7103      so we have to undo it's effects here.  */
7104   if (fixP->fx_pcrel)
7105     {
7106       if (fixP->fx_addsy != NULL
7107 	  && S_IS_DEFINED (fixP->fx_addsy)
7108 	  && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7109 	value += md_pcrel_from (fixP);
7110     }
7111 
7112   /* Remember value for emit_reloc.  */
7113   fixP->fx_addnumber = value;
7114 
7115   switch (fixP->fx_r_type)
7116     {
7117     case BFD_RELOC_HI16_S:
7118       if (fixP->fx_done)        /* For la rd, imm32.  */
7119         {
7120           newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7121           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
7122           newval |= (HI & 0x3fff) << 1;
7123           newval |= ((HI >> 14) & 0x3) << 16;
7124           s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7125         }
7126       break;
7127     case BFD_RELOC_LO16:
7128       if (fixP->fx_done)        /* For la rd, imm32.  */
7129         {
7130           newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7131           LO = (value) & 0xffff;
7132           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
7133           newval |= ((LO >> 14) & 0x3) << 16;
7134           s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7135         }
7136       break;
7137     case BFD_RELOC_SCORE_JMP:
7138       {
7139         content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7140         value = fixP->fx_offset;
7141         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
7142         s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7143       }
7144       break;
7145 
7146     case BFD_RELOC_SCORE_IMM30:
7147       {
7148         content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7149         value = fixP->fx_offset;
7150         value >>= 2;
7151         content = (content & ~0x7f7fff7f80LL)
7152 	  | (((value & 0xff) >> 0) << 7)
7153 	  | (((value & 0x7fff00) >> 8) << 16)
7154 	  | (((value & 0x3f800000) >> 23) << 32);
7155         s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7156         break;
7157       }
7158 
7159     case BFD_RELOC_SCORE_IMM32:
7160       {
7161         content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7162         value = fixP->fx_offset;
7163         content = (content & ~0x7f7fff7fe0LL)
7164 	  | ((value & 0x3ff) << 5)
7165 	  | (((value >> 10) & 0x7fff) << 16)
7166 	  | (((value >> 25) & 0x7f) << 32);
7167         s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7168         break;
7169       }
7170 
7171     case BFD_RELOC_SCORE_BRANCH:
7172       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7173         value = fixP->fx_offset;
7174       else
7175         fixP->fx_done = 1;
7176 
7177       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7178 
7179       /* Don't check c-bit.  */
7180       if (fixP->fx_frag->fr_opcode != 0)
7181         {
7182           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7183             {
7184               as_bad_where (fixP->fx_file, fixP->fx_line,
7185                             _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
7186               return;
7187             }
7188           content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7189           content &= 0xfe00;
7190           content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7191           s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7192           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
7193           fixP->fx_size = 2;
7194         }
7195       else
7196         {
7197           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7198             {
7199               as_bad_where (fixP->fx_file, fixP->fx_line,
7200                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7201               return;
7202             }
7203           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7204           content &= 0xfc00fc01;
7205           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7206           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7207         }
7208       break;
7209     case BFD_RELOC_SCORE16_JMP:
7210       content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7211       content &= 0xf001;
7212       value = fixP->fx_offset & 0xfff;
7213       content = (content & 0xfc01) | (value & 0xffe);
7214       s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7215       break;
7216     case BFD_RELOC_SCORE16_BRANCH:
7217       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7218       /* Don't check c-bit.  */
7219       if (fixP->fx_frag->fr_opcode != 0)
7220         {
7221           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7222               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7223             value = fixP->fx_offset;
7224           else
7225             fixP->fx_done = 1;
7226           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7227             {
7228               as_bad_where (fixP->fx_file, fixP->fx_line,
7229                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7230               return;
7231             }
7232           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7233           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7234           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7235           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7236           fixP->fx_size = 4;
7237           break;
7238         }
7239       else
7240         {
7241           /* In different section.  */
7242           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7243               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7244             value = fixP->fx_offset;
7245           else
7246             fixP->fx_done = 1;
7247 
7248           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7249             {
7250               as_bad_where (fixP->fx_file, fixP->fx_line,
7251                             _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
7252               return;
7253             }
7254 
7255           content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7256           content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7257           s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7258           break;
7259         }
7260 
7261       break;
7262 
7263     case BFD_RELOC_SCORE_BCMP:
7264       if (fixP->fx_frag->fr_opcode != 0)
7265         {
7266           char *buf_ptr = buf;
7267           buf_ptr += 2;
7268 
7269           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7270             value = fixP->fx_offset;
7271           else
7272             fixP->fx_done = 1;
7273 
7274           /* NOTE!!!
7275              bcmp -> cmp! and branch, so value -= 2.  */
7276           value -= 2;
7277 
7278           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7279             {
7280               as_bad_where (fixP->fx_file, fixP->fx_line,
7281                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7282               return;
7283             }
7284 
7285           content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
7286           content &= 0xfc00fc01;
7287           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7288           s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
7289           /* change relocation type to BFD_RELOC_SCORE_BRANCH */
7290           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7291           fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
7292           break;
7293         }
7294       else
7295         {
7296           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7297             value = fixP->fx_offset;
7298           else
7299             fixP->fx_done = 1;
7300 
7301           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7302 
7303           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7304             {
7305               as_bad_where (fixP->fx_file, fixP->fx_line,
7306 			    _(" branch relocation truncate (0x%x)  [-2^9 ~ 2^9-1]"), (unsigned int) value);
7307               return;
7308             }
7309 
7310           value >>= 1;
7311           content &= ~0x03e00381;
7312           content = content
7313 	    | (value & 0x1)
7314 	    | (((value & 0xe) >> 1) << 7)
7315 	    | (((value & 0x1f0) >> 4) << 21);
7316 
7317           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7318           break;
7319         }
7320 
7321     case BFD_RELOC_8:
7322       if (fixP->fx_done || fixP->fx_pcrel)
7323 	s3_md_number_to_chars (buf, value, 1);
7324 #ifdef OBJ_ELF
7325       else
7326         {
7327           value = fixP->fx_offset;
7328           s3_md_number_to_chars (buf, value, 1);
7329         }
7330 #endif
7331       break;
7332 
7333     case BFD_RELOC_16:
7334       if (fixP->fx_done || fixP->fx_pcrel)
7335         s3_md_number_to_chars (buf, value, 2);
7336 #ifdef OBJ_ELF
7337       else
7338         {
7339           value = fixP->fx_offset;
7340           s3_md_number_to_chars (buf, value, 2);
7341         }
7342 #endif
7343       break;
7344     case BFD_RELOC_RVA:
7345     case BFD_RELOC_32:
7346       if (fixP->fx_done || fixP->fx_pcrel)
7347         md_number_to_chars (buf, value, 4);
7348 #ifdef OBJ_ELF
7349       else
7350         {
7351           value = fixP->fx_offset;
7352           md_number_to_chars (buf, value, 4);
7353         }
7354 #endif
7355       break;
7356     case BFD_RELOC_VTABLE_INHERIT:
7357       fixP->fx_done = 0;
7358       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
7359         S_SET_WEAK (fixP->fx_addsy);
7360       break;
7361     case BFD_RELOC_VTABLE_ENTRY:
7362       fixP->fx_done = 0;
7363       break;
7364     case BFD_RELOC_SCORE_GPREL15:
7365       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7366       /* c-bit.  */
7367       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
7368         fixP->fx_r_type = BFD_RELOC_NONE;
7369       fixP->fx_done = 0;
7370       break;
7371     case BFD_RELOC_SCORE_GOT15:
7372     case BFD_RELOC_SCORE_DUMMY_HI16:
7373     case BFD_RELOC_SCORE_GOT_LO16:
7374     case BFD_RELOC_SCORE_CALL15:
7375     case BFD_RELOC_GPREL32:
7376       break;
7377     case BFD_RELOC_NONE:
7378     default:
7379       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
7380     }
7381 }
7382 
7383 static arelent **
7384 s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7385 {
7386   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
7387   arelent *reloc;
7388   bfd_reloc_code_real_type code;
7389   const char *type;
7390 
7391   reloc = retval[0] = XNEW (arelent);
7392   retval[1] = NULL;
7393 
7394   reloc->sym_ptr_ptr = XNEW (asymbol *);
7395   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7396   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7397   reloc->addend = fixp->fx_offset;
7398 
7399   /* If this is a variant frag, we may need to adjust the existing
7400      reloc and generate a new one.  */
7401   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
7402     {
7403       /* Update instruction imm bit.  */
7404       offsetT newval;
7405       unsigned short off;
7406       char *buf;
7407 
7408       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
7409       newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7410       off = fixp->fx_offset >> 16;
7411       newval |= (off & 0x3fff) << 1;
7412       newval |= ((off >> 14) & 0x3) << 16;
7413       s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7414 
7415       buf += s3_INSN_SIZE;
7416       newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7417       off = fixp->fx_offset & 0xffff;
7418       newval |= ((off & 0x3fff) << 1);
7419       newval |= (((off >> 14) & 0x3) << 16);
7420       s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7421 
7422       retval[1] = XNEW (arelent);
7423       retval[2] = NULL;
7424       retval[1]->sym_ptr_ptr = XNEW (asymbol *);
7425       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7426       retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
7427 
7428       retval[1]->addend = 0;
7429       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
7430       gas_assert (retval[1]->howto != NULL);
7431 
7432       fixp->fx_r_type = BFD_RELOC_HI16_S;
7433     }
7434 
7435   code = fixp->fx_r_type;
7436   switch (fixp->fx_r_type)
7437     {
7438     case BFD_RELOC_32:
7439       if (fixp->fx_pcrel)
7440         {
7441           code = BFD_RELOC_32_PCREL;
7442           break;
7443         }
7444       /* Fall through.  */
7445     case BFD_RELOC_HI16_S:
7446     case BFD_RELOC_LO16:
7447     case BFD_RELOC_SCORE_JMP:
7448     case BFD_RELOC_SCORE_BRANCH:
7449     case BFD_RELOC_SCORE16_JMP:
7450     case BFD_RELOC_SCORE16_BRANCH:
7451     case BFD_RELOC_SCORE_BCMP:
7452     case BFD_RELOC_VTABLE_ENTRY:
7453     case BFD_RELOC_VTABLE_INHERIT:
7454     case BFD_RELOC_SCORE_GPREL15:
7455     case BFD_RELOC_SCORE_GOT15:
7456     case BFD_RELOC_SCORE_DUMMY_HI16:
7457     case BFD_RELOC_SCORE_GOT_LO16:
7458     case BFD_RELOC_SCORE_CALL15:
7459     case BFD_RELOC_GPREL32:
7460     case BFD_RELOC_NONE:
7461     case BFD_RELOC_SCORE_IMM30:
7462     case BFD_RELOC_SCORE_IMM32:
7463       code = fixp->fx_r_type;
7464       break;
7465     default:
7466       type = _("<unknown>");
7467       as_bad_where (fixp->fx_file, fixp->fx_line,
7468                     _("cannot represent %s relocation in this object file format"), type);
7469       return NULL;
7470     }
7471 
7472   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7473   if (reloc->howto == NULL)
7474     {
7475       as_bad_where (fixp->fx_file, fixp->fx_line,
7476                     _("cannot represent %s relocation in this object file format1"),
7477                     bfd_get_reloc_code_name (code));
7478       return NULL;
7479     }
7480   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
7481      vtable entry to be used in the relocation's section offset.  */
7482   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
7483     reloc->address = fixp->fx_offset;
7484 
7485   return retval;
7486 }
7487 
7488 void
7489 md_assemble (char *str)
7490 {
7491   if (score3)
7492     s3_assemble (str);
7493   else
7494     s7_assemble (str);
7495 }
7496 
7497 /* We handle all bad expressions here, so that we can report the faulty
7498    instruction in the error message.  */
7499 void
7500 md_operand (expressionS * exp)
7501 {
7502   if (score3)
7503     s3_operand (exp);
7504   else
7505     s7_operand (exp);
7506 }
7507 
7508 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7509    for use in the a.out file, and stores them in the array pointed to by buf.
7510    This knows about the endian-ness of the target machine and does
7511    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
7512    2 (short) and 4 (long)  Floating numbers are put out as a series of
7513    LITTLENUMS (shorts, here at least).  */
7514 void
7515 md_number_to_chars (char *buf, valueT val, int n)
7516 {
7517   if (score3)
7518     s3_number_to_chars (buf, val, n);
7519   else
7520     s7_number_to_chars (buf, val, n);
7521 }
7522 
7523 /* Turn a string in input_line_pointer into a floating point constant
7524    of type TYPE, and store the appropriate bytes in *LITP.  The number
7525    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
7526    returned, or NULL on OK.
7527 
7528    Note that fp constants aren't represent in the normal way on the ARM.
7529    In big endian mode, things are as expected.  However, in little endian
7530    mode fp constants are big-endian word-wise, and little-endian byte-wise
7531    within the words.  For example, (double) 1.1 in big endian mode is
7532    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7533    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
7534 const char *
7535 md_atof (int type, char *litP, int *sizeP)
7536 {
7537   if (score3)
7538     return s3_atof (type, litP, sizeP);
7539   else
7540     return s7_atof (type, litP, sizeP);
7541 }
7542 
7543 void
7544 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
7545 {
7546   if (score3)
7547     s3_frag_check (fragp);
7548   else
7549     s7_frag_check (fragp);
7550 }
7551 
7552 /* Implementation of TC_VALIDATE_FIX.
7553    Called before md_apply_fix() and after md_convert_frag().  */
7554 void
7555 score_validate_fix (fixS *fixP)
7556 {
7557   if (score3)
7558     s3_validate_fix (fixP);
7559   else
7560     s7_validate_fix (fixP);
7561 }
7562 
7563 int
7564 score_force_relocation (struct fix *fixp)
7565 {
7566   if (score3)
7567     return s3_force_relocation (fixp);
7568   else
7569     return s7_force_relocation (fixp);
7570 }
7571 
7572 /* Implementation of md_frag_check.
7573    Called after md_convert_frag().  */
7574 bfd_boolean
7575 score_fix_adjustable (fixS * fixP)
7576 {
7577   if (score3)
7578     return s3_fix_adjustable (fixP);
7579   else
7580     return s7_fix_adjustable (fixP);
7581 }
7582 
7583 void
7584 score_elf_final_processing (void)
7585 {
7586   if (score3)
7587     s3_elf_final_processing ();
7588   else
7589     s7_elf_final_processing ();
7590 }
7591 
7592 /* In this function, we determine whether s3_GP instruction should do relaxation,
7593    for the label being against was known now.
7594    Doing this here but not in md_relax_frag() can induce iteration times
7595    in stage of doing relax.  */
7596 int
7597 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
7598 {
7599   if (score3)
7600     return s3_estimate_size_before_relax (fragp, sec);
7601   else
7602     return s7_estimate_size_before_relax (fragp, sec);
7603 }
7604 
7605 int
7606 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
7607 {
7608   if (score3)
7609     return s3_relax_frag (sec, fragp, stretch);
7610   else
7611     return s7_relax_frag (sec, fragp, stretch);
7612 }
7613 
7614 void
7615 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7616 {
7617   if (score3)
7618     return s3_convert_frag (abfd, sec, fragp);
7619   else
7620     return s7_convert_frag (abfd, sec, fragp);
7621 }
7622 
7623 long
7624 md_pcrel_from (fixS * fixP)
7625 {
7626   if (score3)
7627     return s3_pcrel_from (fixP);
7628   else
7629     return s7_pcrel_from (fixP);
7630 }
7631 
7632 /* Round up a section size to the appropriate boundary.  */
7633 valueT
7634 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7635 {
7636   if (score3)
7637     return s3_section_align (segment, size);
7638   else
7639     return s7_section_align (segment, size);
7640 }
7641 
7642 void
7643 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
7644 {
7645   if (score3)
7646     return s3_apply_fix (fixP, valP, seg);
7647   else
7648     return s7_apply_fix (fixP, valP, seg);
7649 }
7650 
7651 /* Translate internal representation of relocation info to BFD target format.  */
7652 arelent **
7653 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7654 {
7655   if (score3)
7656     return s3_gen_reloc (section, fixp);
7657   else
7658     return s7_gen_reloc (section, fixp);
7659 }
7660 
7661 void
7662 md_begin (void)
7663 {
7664   s3_begin ();
7665   s7_begin ();
7666 }
7667 
7668 static void
7669 score_set_mach (const char *arg)
7670 {
7671   if (strcmp (arg, MARCH_SCORE3) == 0)
7672     {
7673       score3 = 1;
7674       score7 = 0;
7675       s3_score3d = 1;
7676     }
7677   else if (strcmp (arg, MARCH_SCORE7) == 0)
7678     {
7679       score3 = 0;
7680       score7 = 1;
7681       s7_score7d = 1;
7682       s7_university_version = 0;
7683       s7_vector_size = s7_SCORE7_PIPELINE;
7684     }
7685   else if (strcmp (arg, MARCH_SCORE5) == 0)
7686     {
7687       score3 = 0;
7688       score7 = 1;
7689       s7_score7d = 1;
7690       s7_university_version = 0;
7691       s7_vector_size = s7_SCORE5_PIPELINE;
7692     }
7693   else if (strcmp (arg, MARCH_SCORE5U) == 0)
7694     {
7695       score3 = 0;
7696       score7 = 1;
7697       s7_score7d = 1;
7698       s7_university_version = 1;
7699       s7_vector_size = s7_SCORE5_PIPELINE;
7700     }
7701   else
7702     {
7703       as_bad (_("unknown architecture `%s'\n"), arg);
7704     }
7705 }
7706 
7707 int
7708 md_parse_option (int c, const char *arg)
7709 {
7710   switch (c)
7711     {
7712 #ifdef OPTION_EB
7713     case OPTION_EB:
7714       target_big_endian = 1;
7715       break;
7716 #endif
7717 #ifdef OPTION_EL
7718     case OPTION_EL:
7719       target_big_endian = 0;
7720       break;
7721 #endif
7722     case OPTION_FIXDD:
7723       s3_fix_data_dependency = 1;
7724       s7_fix_data_dependency = 1;
7725       break;
7726     case OPTION_NWARN:
7727       s3_warn_fix_data_dependency = 0;
7728       s7_warn_fix_data_dependency = 0;
7729       break;
7730     case OPTION_SCORE5:
7731       score3 = 0;
7732       score7 = 1;
7733       s7_university_version = 0;
7734       s7_vector_size = s7_SCORE5_PIPELINE;
7735       break;
7736     case OPTION_SCORE5U:
7737       score3 = 0;
7738       score7 = 1;
7739       s7_university_version = 1;
7740       s7_vector_size = s7_SCORE5_PIPELINE;
7741       break;
7742     case OPTION_SCORE7:
7743       score3 = 0;
7744       score7 = 1;
7745       s7_score7d = 1;
7746       s7_university_version = 0;
7747       s7_vector_size = s7_SCORE7_PIPELINE;
7748       break;
7749     case OPTION_SCORE3:
7750       score3 = 1;
7751       score7 = 0;
7752       s3_score3d = 1;
7753       break;
7754     case OPTION_R1:
7755       s3_nor1 = 0;
7756       s7_nor1 = 0;
7757       break;
7758     case 'G':
7759       s3_g_switch_value = atoi (arg);
7760       s7_g_switch_value = atoi (arg);
7761       break;
7762     case OPTION_O0:
7763       s3_g_opt = 0;
7764       s7_g_opt = 0;
7765       break;
7766     case OPTION_SCORE_VERSION:
7767       printf (_("Sunplus-v2-0-0-20060510\n"));
7768       break;
7769     case OPTION_PIC:
7770       s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now.  */
7771       s7_score_pic = s7_PIC;
7772       s3_g_switch_value = 0;    /* Must set -G num as 0 to generate s3_PIC code.  */
7773       s7_g_switch_value = 0;    /* Must set -G num as 0 to generate s7_PIC code.  */
7774       break;
7775     case OPTION_MARCH:
7776       score_set_mach (arg);
7777       break;
7778     default:
7779       return 0;
7780     }
7781   return 1;
7782 }
7783 
7784 void
7785 md_show_usage (FILE * fp)
7786 {
7787   fprintf (fp, _(" Score-specific assembler options:\n"));
7788 #ifdef OPTION_EB
7789   fprintf (fp, _("\
7790         -EB\t\tassemble code for a big-endian cpu\n"));
7791 #endif
7792 
7793 #ifdef OPTION_EL
7794   fprintf (fp, _("\
7795         -EL\t\tassemble code for a little-endian cpu\n"));
7796 #endif
7797 
7798   fprintf (fp, _("\
7799         -FIXDD\t\tfix data dependencies\n"));
7800   fprintf (fp, _("\
7801         -NWARN\t\tdo not print warning message when fixing data dependencies\n"));
7802   fprintf (fp, _("\
7803         -SCORE5\t\tassemble code for target SCORE5\n"));
7804   fprintf (fp, _("\
7805         -SCORE5U\tassemble code for target SCORE5U\n"));
7806   fprintf (fp, _("\
7807         -SCORE7\t\tassemble code for target SCORE7 [default]\n"));
7808   fprintf (fp, _("\
7809         -SCORE3\t\tassemble code for target SCORE3\n"));
7810   fprintf (fp, _("\
7811         -march=score7\tassemble code for target SCORE7 [default]\n"));
7812   fprintf (fp, _("\
7813         -march=score3\tassemble code for target SCORE3\n"));
7814   fprintf (fp, _("\
7815         -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
7816   fprintf (fp, _("\
7817         -KPIC\t\tgenerate PIC\n"));
7818   fprintf (fp, _("\
7819         -O0\t\tdo not perform any optimizations\n"));
7820   fprintf (fp, _("\
7821         -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n"));
7822   fprintf (fp, _("\
7823         -V \t\tSunplus release version\n"));
7824 }
7825