[PATCH, BINUTILS, AARCH64, 1/9] Add -march=armv8.5-a and related internal feature...
[external/binutils.git] / gas / config / tc-score.c
1 /* tc-score.c -- Assembler for Score
2    Copyright (C) 2006-2018 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_MAX_LITTLENUMS 6
304 #define s3_INSN_NAME_LEN 16
305
306 /* Relax will need some padding for alignment.  */
307 #define s3_RELAX_PAD_BYTE 3
308
309
310 #define s3_USE_GLOBAL_POINTER_OPT 1
311
312 /* Enumeration matching entries in table above.  */
313 enum s3_score_reg_type
314 {
315   s3_REG_TYPE_SCORE = 0,
316 #define s3_REG_TYPE_FIRST s3_REG_TYPE_SCORE
317   s3_REG_TYPE_SCORE_SR = 1,
318   s3_REG_TYPE_SCORE_CR = 2,
319   s3_REG_TYPE_MAX = 3
320 };
321
322 enum s3_score_pic_level
323 {
324   s3_NO_PIC,
325   s3_PIC
326 };
327 static enum s3_score_pic_level s3_score_pic = s3_NO_PIC;
328
329 enum s3_insn_type_for_dependency
330 {
331   s3_D_mtcr,
332   s3_D_all_insn
333 };
334
335 struct s3_insn_to_dependency
336 {
337   const char *insn_name;
338   enum s3_insn_type_for_dependency type;
339 };
340
341 struct s3_data_dependency
342 {
343   enum s3_insn_type_for_dependency pre_insn_type;
344   char pre_reg[6];
345   enum s3_insn_type_for_dependency cur_insn_type;
346   char cur_reg[6];
347   int bubblenum_7;
348   int bubblenum_3;
349   int warn_or_error;           /* warning - 0; error - 1  */
350 };
351
352 static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] =
353 {
354   /* move special instruction.  */
355   {"mtcr",      s3_D_mtcr},
356 };
357
358 static const struct s3_data_dependency s3_data_dependency_table[] =
359 {
360   /* Status register.  */
361   {s3_D_mtcr, "cr0", s3_D_all_insn, "", 5, 1, 0},
362 };
363
364 /* Used to contain constructed error messages.  */
365 static char s3_err_msg[255];
366
367 static int s3_fix_data_dependency = 0;
368 static int s3_warn_fix_data_dependency = 1;
369
370 static int s3_in_my_get_expression = 0;
371
372 /* Default, pop warning message when using r1.  */
373 static int s3_nor1 = 1;
374
375 /* Default will do instruction relax, -O0 will set s3_g_opt = 0.  */
376 static unsigned int s3_g_opt = 1;
377
378 /* The size of the small data section.  */
379 static unsigned int s3_g_switch_value = 8;
380
381 static segT s3_pdr_seg;
382
383 struct s3_score_it
384 {
385   char name[s3_INSN_NAME_LEN];
386   bfd_vma instruction;
387   bfd_vma relax_inst;
388   int size;
389   int relax_size;
390   enum score_insn_type type;
391   char str[s3_MAX_LITERAL_POOL_SIZE];
392   const char *error;
393   int bwarn;
394   char reg[s3_INSN_NAME_LEN];
395   struct
396   {
397     bfd_reloc_code_real_type type;
398     expressionS exp;
399     int pc_rel;
400   }reloc;
401 };
402 static struct s3_score_it s3_inst;
403
404 typedef struct s3_proc
405 {
406   symbolS *isym;
407   unsigned long reg_mask;
408   unsigned long reg_offset;
409   unsigned long fpreg_mask;
410   unsigned long leaf;
411   unsigned long frame_offset;
412   unsigned long frame_reg;
413   unsigned long pc_reg;
414 } s3_procS;
415 static s3_procS s3_cur_proc;
416 static s3_procS *s3_cur_proc_ptr;
417 static int s3_numprocs;
418
419
420 /* Structure for a hash table entry for a register.  */
421 struct s3_reg_entry
422 {
423   const char *name;
424   int number;
425 };
426
427 static const struct s3_reg_entry s3_score_rn_table[] =
428 {
429   {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
430   {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
431   {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
432   {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
433   {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
434   {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
435   {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
436   {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
437   {NULL, 0}
438 };
439
440 static const struct s3_reg_entry s3_score_srn_table[] =
441 {
442   {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
443   {NULL, 0}
444 };
445
446 static const struct s3_reg_entry s3_score_crn_table[] =
447 {
448   {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
449   {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
450   {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
451   {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
452   {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
453   {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
454   {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
455   {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
456   {NULL, 0}
457 };
458
459 struct s3_reg_map
460 {
461   const struct s3_reg_entry *names;
462   int max_regno;
463   struct hash_control *htab;
464   const char *expected;
465 };
466
467 static struct s3_reg_map s3_all_reg_maps[] =
468 {
469   {s3_score_rn_table, 31, NULL, N_("S+core register expected")},
470   {s3_score_srn_table, 2, NULL, N_("S+core special-register expected")},
471   {s3_score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
472 };
473
474 static struct hash_control *s3_score_ops_hsh = NULL;
475 static struct hash_control *s3_dependency_insn_hsh = NULL;
476
477
478 struct s3_datafield_range
479 {
480   int data_type;
481   int bits;
482   int range[2];
483 };
484
485 static struct s3_datafield_range s3_score_df_range[] =
486 {
487   {_IMM4,             4,  {0, (1 << 4) - 1}},           /* (     0 ~ 15   ) */
488   {_IMM5,             5,  {0, (1 << 5) - 1}},           /* (     0 ~ 31   ) */
489   {_IMM8,             8,  {0, (1 << 8) - 1}},           /* (     0 ~ 255  ) */
490   {_IMM14,            14, {0, (1 << 14) - 1}},          /* (     0 ~ 16383) */
491   {_IMM15,            15, {0, (1 << 15) - 1}},          /* (     0 ~ 32767) */
492   {_IMM16,            16, {0, (1 << 16) - 1}},          /* (     0 ~ 65535) */
493   {_SIMM10,           10, {-(1 << 9), (1 << 9) - 1}},   /* (  -512 ~ 511  ) */
494   {_SIMM12,           12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */
495   {_SIMM14,           14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */
496   {_SIMM15,           15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */
497   {_SIMM16,           16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
498   {_SIMM14_NEG,       14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */
499   {_IMM16_NEG,        16, {0, (1 << 16) - 1}},          /* (-65535 ~ 0    ) */
500   {_SIMM16_NEG,       16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
501   {_IMM20,            20, {0, (1 << 20) - 1}},
502   {_IMM25,            25, {0, (1 << 25) - 1}},
503   {_DISP8div2,        8,  {-(1 << 8), (1 << 8) - 1}},   /* (  -256 ~ 255  ) */
504   {_DISP11div2,       11, {0, 0}},
505   {_DISP19div2,       19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */
506   {_DISP24div2,       24, {0, 0}},
507   {_VALUE,            32, {0, ((unsigned int)1 << 31) - 1}},
508   {_VALUE_HI16,       16, {0, (1 << 16) - 1}},
509   {_VALUE_LO16,       16, {0, (1 << 16) - 1}},
510   {_VALUE_LDST_LO16,  16, {0, (1 << 16) - 1}},
511   {_SIMM16_LA,        16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
512   {_IMM5_RSHIFT_1,    5,  {0, (1 << 6) - 1}},           /* (     0 ~ 63   ) */
513   {_IMM5_RSHIFT_2,    5,  {0, (1 << 7) - 1}},           /* (     0 ~ 127  ) */
514   {_SIMM16_LA_POS,    16, {0, (1 << 15) - 1}},          /* (     0 ~ 32767) */
515   {_IMM5_RANGE_8_31,  5,  {8, 31}},                     /* But for cop0 the valid data : (8 ~ 31). */
516   {_IMM10_RSHIFT_2,   10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */
517   {_SIMM10,           10, {0, (1 << 10) - 1}},          /* ( -1024 ~ 1023 ) */
518   {_SIMM12,           12, {0, (1 << 12) - 1}},          /* ( -2048 ~ 2047 ) */
519   {_SIMM14,           14, {0, (1 << 14) - 1}},          /* ( -8192 ~ 8191 ) */
520   {_SIMM15,           15, {0, (1 << 15) - 1}},          /* (-16384 ~ 16383) */
521   {_SIMM16,           16, {0, (1 << 16) - 1}},          /* (-65536 ~ 65536) */
522   {_SIMM14_NEG,       14, {0, (1 << 16) - 1}},          /* ( -8191 ~ 8192 ) */
523   {_IMM16_NEG,        16, {0, (1 << 16) - 1}},          /* ( 65535 ~ 0    ) */
524   {_SIMM16_NEG,       16, {0, (1 << 16) - 1}},          /* ( 65535 ~ 0    ) */
525   {_IMM20,            20, {0, (1 << 20) - 1}},          /* (-32768 ~ 32767) */
526   {_IMM25,            25, {0, (1 << 25) - 1}},          /* (-32768 ~ 32767) */
527   {_GP_IMM15,         15, {0, (1 << 15) - 1}},          /* (     0 ~ 65535) */
528   {_GP_IMM14,         14, {0, (1 << 14) - 1}},          /* (     0 ~ 65535) */
529   {_SIMM16_pic,       16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
530   {_IMM16_LO16_pic,   16, {0, (1 << 16) - 1}},          /* ( 65535 ~ 0    ) */
531   {_IMM16_pic,        16, {0, (1 << 16) - 1}},          /* (     0 ~ 65535) */
532   {_SIMM5,            5,  {-(1 << 4), (1 << 4) - 1}},   /* (   -16 ~ 15   ) */
533   {_SIMM6,            6,  {-(1 << 5), (1 << 5) - 1}},   /* (   -32 ~ 31   ) */
534   {_IMM32,            32, {0, 0xfffffff}},
535   {_SIMM32,           32, {-0x80000000, 0x7fffffff}},
536   {_IMM11,            11, {0, (1 << 11) - 1}},
537 };
538
539 struct s3_asm_opcode
540 {
541   /* Instruction name.  */
542   const char *template_name;
543
544   /* Instruction Opcode.  */
545   bfd_vma value;
546
547   /* Instruction bit mask.  */
548   bfd_vma bitmask;
549
550   /* Relax instruction opcode.  0x8000 imply no relaxation.  */
551   bfd_vma relax_value;
552
553   /* Instruction type.  */
554   enum score_insn_type type;
555
556   /* Function to call to parse args.  */
557   void (*parms) (char *);
558 };
559
560 static const struct s3_asm_opcode s3_score_ldst_insns[] =
561 {
562   {"lw",        0x20000000, 0x3e000000, 0x1000,     Rd_rvalueRs_SI15,     s3_do_ldst_insn},
563   {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s3_do_ldst_insn},
564   {"lw",        0x0e000000, 0x3e000007, 0x0040,     Rd_rvalueRs_postSI12, s3_do_ldst_insn},
565   {"lh",        0x22000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s3_do_ldst_insn},
566   {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s3_do_ldst_insn},
567   {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s3_do_ldst_insn},
568   {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s3_do_ldst_insn},
569   {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s3_do_ldst_insn},
570   {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s3_do_ldst_insn},
571   {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s3_do_ldst_insn},
572   {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s3_do_ldst_insn},
573   {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s3_do_ldst_insn},
574   {"sw",        0x28000000, 0x3e000000, 0x2000,     Rd_lvalueRs_SI15,     s3_do_ldst_insn},
575   {"sw",        0x06000004, 0x3e000007, 0x0060,     Rd_lvalueRs_preSI12,  s3_do_ldst_insn},
576   {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s3_do_ldst_insn},
577   {"sh",        0x2a000000, 0x3e000000, 0x8000,     Rd_lvalueRs_SI15,     s3_do_ldst_insn},
578   {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  s3_do_ldst_insn},
579   {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s3_do_ldst_insn},
580   {"lbu",       0x2c000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s3_do_ldst_insn},
581   {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s3_do_ldst_insn},
582   {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s3_do_ldst_insn},
583   {"sb",        0x2e000000, 0x3e000000, 0x8000,     Rd_lvalueRs_SI15,     s3_do_ldst_insn},
584   {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  s3_do_ldst_insn},
585   {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s3_do_ldst_insn},
586 };
587
588 static const struct s3_asm_opcode s3_score_insns[] =
589 {
590   {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_dsp3},
591   {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_dsp3},
592   {"add",       0x00000010, 0x3e0003ff, 0x4800,     Rd_Rs_Rs,             s3_do_rdrsrs},
593   {"add.c",     0x00000011, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
594   {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
595   {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
596   {"addc.c",    0x00000013, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
597   {"addi",      0x02000000, 0x3e0e0001, 0x5c00,     Rd_SI16,              s3_do_rdsi16},
598   {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_rdsi16},
599   {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_rdi16},
600   {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_rdi16},
601   {"addi!",     0x5c00,     0x7c00,     0x8000,     Rd_SI6,               s3_do16_addi},
602   {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s3_do_rdrssi14},
603   {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s3_do_rdrssi14},
604
605   /* add.c <-> add!.  */
606   {"add!",      0x4800,     0x7f00,     0x8000,     Rd_Rs,                s3_do16_rdrs2},
607   {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_sub_rdsi16},
608   {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_sub_rdsi16},
609   {"subis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_sub_rdi16},
610   {"subis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s3_do_sub_rdi16},
611   {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s3_do_sub_rdrssi14},
612   {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s3_do_sub_rdrssi14},
613   {"and",       0x00000020, 0x3e0003ff, 0x4b00,     Rd_Rs_Rs,             s3_do_rdrsrs},
614   {"and.c",     0x00000021, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
615   {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
616   {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
617   {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
618   {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
619   {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            s3_do_rdrsi14},
620   {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            s3_do_rdrsi14},
621
622   /* and.c <-> and!.  */
623   {"and!",      0x4b00,     0x7f00,     0x8000,     Rd_Rs,                s3_do16_rdrs2},
624   {"bcs",       0x08000000, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
625   {"bcc",       0x08000400, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
626   {"bcnz",      0x08003800, 0x3e007c01, 0x3200,     PC_DISP19div2,        s3_do_branch},
627   {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
628   {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
629   {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
630   {"bcnz!",     0x3200,     0x7f00,     0x08003800, PC_DISP8div2,         s3_do16_branch},
631   {"beq",       0x08001000, 0x3e007c01, 0x3800,     PC_DISP19div2,        s3_do_branch},
632   {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
633   {"beq!",      0x3800,     0x7e00,     0x08001000, PC_DISP8div2,         s3_do16_branch},
634   {"bgtu",      0x08000800, 0x3e007c01, 0x3400,     PC_DISP19div2,        s3_do_branch},
635   {"bgt",       0x08001800, 0x3e007c01, 0x3c00,     PC_DISP19div2,        s3_do_branch},
636   {"bge",       0x08002000, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
637   {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
638   {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
639   {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
640   {"bgtu!",     0x3400,     0x7e00,     0x08000800, PC_DISP8div2,         s3_do16_branch},
641   {"bgt!",      0x3c00,     0x7e00,     0x08001800, PC_DISP8div2,         s3_do16_branch},
642   {"bitclr",    0x00000028, 0x3e0003ff, 0x5000,     Rd_Rs_I5,             s3_do_rdrsi5},
643   {"bitclr.c",  0x00000029, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
644
645   {"mbitclr",   0x00000064, 0x3e00007e, 0x8000,     Ra_I9_I5,             s3_do_mbitclr},
646   {"mbitset",   0x0000006c, 0x3e00007e, 0x8000,     Ra_I9_I5,             s3_do_mbitset},
647
648   {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
649   {"bitset",    0x0000002a, 0x3e0003ff, 0x5200,     Rd_Rs_I5,             s3_do_rdrsi5},
650   {"bitset.c",  0x0000002b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
651   {"bittst.c",  0x0000002d, 0x3e0003ff, 0x5400,     x_Rs_I5,              s3_do_xrsi5},
652   {"bittgl",    0x0000002e, 0x3e0003ff, 0x5600,     Rd_Rs_I5,             s3_do_rdrsi5},
653   {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
654   {"bitclr!",   0x5000,     0x7e00,     0x8000,     Rd_I5,                s3_do16_rdi5},
655   {"bitset!",   0x5200,     0x7e00,     0x8000,     Rd_I5,                s3_do16_rdi5},
656   {"bittst!",   0x5400,     0x7e00,     0x8000,     Rd_I5,                s3_do16_rdi5},
657   {"bittgl!",   0x5600,     0x7e00,     0x8000,     Rd_I5,                s3_do16_rdi5},
658   {"bleu",      0x08000c00, 0x3e007c01, 0x3600,     PC_DISP19div2,        s3_do_branch},
659   {"ble",       0x08001c00, 0x3e007c01, 0x3e00,     PC_DISP19div2,        s3_do_branch},
660   {"blt",       0x08002400, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
661   {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
662   {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
663   {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
664   {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
665   {"bleu!",     0x3600,     0x7e00,     0x08000c00, PC_DISP8div2,         s3_do16_branch},
666   {"ble!",      0x3e00,     0x7e00,     0x08001c00, PC_DISP8div2,         s3_do16_branch},
667   {"bmi",       0x08002800, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
668   {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
669   {"bne",       0x08001400, 0x3e007c01, 0x3a00,     PC_DISP19div2,        s3_do_branch},
670   {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
671   {"bne!",      0x3a00,     0x7e00,     0x08001400, PC_DISP8div2,         s3_do16_branch},
672   {"bpl",       0x08002c00, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
673   {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
674   {"brcs",      0x00000008, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
675   {"brcc",      0x00000408, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
676   {"brgtu",     0x00000808, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
677   {"brleu",     0x00000c08, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
678   {"breq",      0x00001008, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
679   {"brne",      0x00001408, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
680   {"brgt",      0x00001808, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
681   {"brle",      0x00001c08, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
682   {"brge",      0x00002008, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
683   {"brlt",      0x00002408, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
684   {"brmi",      0x00002808, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
685   {"brpl",      0x00002c08, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
686   {"brvs",      0x00003008, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
687   {"brvc",      0x00003408, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
688   {"brcnz",     0x00003808, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
689   {"br",        0x00003c08, 0x3e007fff, 0x0080,     x_Rs_x,               s3_do_rs},
690   {"brcsl",     0x00000009, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
691   {"brccl",     0x00000409, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
692   {"brgtul",    0x00000809, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
693   {"brleul",    0x00000c09, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
694   {"breql",     0x00001009, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
695   {"brnel",     0x00001409, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
696   {"brgtl",     0x00001809, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
697   {"brlel",     0x00001c09, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
698   {"brgel",     0x00002009, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
699   {"brltl",     0x00002409, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
700   {"brmil",     0x00002809, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
701   {"brpll",     0x00002c09, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
702   {"brvsl",     0x00003009, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
703   {"brvcl",     0x00003409, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
704   {"brcnzl",    0x00003809, 0x3e007fff, 0x8000,     x_Rs_x,               s3_do_rs},
705   {"brl",       0x00003c09, 0x3e007fff, 0x00a0,     x_Rs_x,               s3_do_rs},
706   {"br!",       0x0080,     0x7fe0,     0x8000,     x_Rs,                 s3_do16_br},
707   {"brl!",      0x00a0,     0x7fe0,     0x8000,     x_Rs,                 s3_do16_br},
708   {"brr!",      0x00c0,     0x7fe0,     0x8000,     x_Rs,                 s3_do16_brr},
709   {"bvs",       0x08003000, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
710   {"bvc",       0x08003400, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
711   {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
712   {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s3_do_branch},
713   {"b!",        0x3000,     0x7e00,     0x08003c00, PC_DISP8div2,         s3_do16_branch},
714   {"b",         0x08003c00, 0x3e007c01, 0x3000,     PC_DISP19div2,        s3_do_branch},
715   {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    s3_do_cache},
716   {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      s3_do_ceinst},
717   {"clz",       0x0000001c, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
718   {"cmp.c",     0x00300019, 0x3ff003ff, 0x4400,     x_Rs_Rs,              s3_do_rsrs},
719   {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               s3_do_rs},
720   {"cmpi.c",    0x02040001, 0x3e0e0001, 0x6000,     Rd_SI16,              s3_do_rdsi16},
721
722   /* cmp.c <-> cmp!.  */
723   {"cmp!",      0x4400,     0x7c00,     0x8000,     Rd_Rs,                s3_do16_mv_cmp},
724   {"cmpi!",     0x6000,     0x7c00,     0x8000,     Rd_SI5,               s3_do16_cmpi},
725   {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s3_do_crdcrscrsimm5},
726   {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s3_do_crdcrscrsimm5},
727   {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s3_do_crdcrscrsimm5},
728   {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               s3_do_empty},
729   {"disint!",    0x00e0,     0xffe1,     0x8000,     NO16_OPD,               s3_do16_int},
730   {"enint!",     0x00e1,     0xffe1,     0x8000,     NO16_OPD,               s3_do16_int},
731   {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
732   {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
733   {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
734   {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
735   {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
736   {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
737   {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
738   {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
739   {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        s3_do_jump},
740   {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        s3_do_jump},
741   {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        s3_do_ldst_atomic},
742   {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     s3_do_ldst_unalign},
743   {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    s3_do_ldst_unalign},
744   {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    s3_do_ldst_unalign},
745   {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s3_do_ldst_cop},
746   {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s3_do_ldst_cop},
747   {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s3_do_ldst_cop},
748
749   /* s3_inst.relax */
750   {"ldi",       0x020c0000, 0x3e0e0000, 0x6400,     Rd_SI16,              s3_do_rdsi16},
751   {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               s3_do_ldis},
752
753   /* ldi <-> ldiu!.  */
754   {"ldiu!",     0x6400,     0x7c00,     0x8000,     Rd_I5,                s3_do16_ldiu},
755
756   /*ltbb! , ltbh! ltbw! */
757   {"ltbw",      0x00000032, 0x03ff,     0x8000,     Rd_Rs_Rs,             s3_do_ltb},
758   {"ltbh",      0x00000132, 0x03ff,     0x8000,     Rd_Rs_Rs,             s3_do_ltb},
759   {"ltbb",      0x00000332, 0x03ff,     0x8000,     Rd_Rs_Rs,             s3_do_ltb},
760   {"lw!",       0x1000,     0x7000,     0x8000,     Rd_rvalueRs,          s3_do16_ldst_insn},
761   {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               s3_do_rd},
762   {"mfcel!",    0x7100,     0x7ff0,     0x00000448, x_Rs,                 s3_do16_dsp},
763   {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
764   {"mad.f!",    0x7400,     0x7f00,     0x38000080, Rd_Rs,                s3_do16_dsp2},
765   {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
766   {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
767   {"madh.fs!",  0x7b00,     0x7f00,     0x380002c3, Rd_Rs,                s3_do16_dsp2},
768   {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
769   {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
770   {"madl.fs!",  0x7a00,     0x7f00,     0x380000c2, Rd_Rs,                s3_do16_dsp2},
771   {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
772   {"madu!",     0x7500,     0x7f00,     0x38000020, Rd_Rs,                s3_do16_dsp2},
773   {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
774   {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
775   {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
776   {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
777   {"mazh.f!",   0x7900,     0x7f00,     0x3800038c, Rd_Rs,                s3_do16_dsp2},
778   {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
779   {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
780   {"mazl.f!",   0x7800,     0x7f00,     0x38000182, Rd_Rs,                s3_do16_dsp2},
781   {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               s3_do_rd},
782   {"mfceh!",    0x7110,     0x7ff0,     0x00000848, x_Rs,                 s3_do16_dsp},
783   {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
784   {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              s3_do_rdsrs},
785   {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
786   {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
787   {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
788   {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
789   {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
790   {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
791   {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
792   {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
793   {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
794   {"msb.f!",    0x7600,     0x7f00,     0x38000081, Rd_Rs,                s3_do16_dsp2},
795   {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
796   {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
797   {"msbh.fs!",  0x7f00,     0x7f00,     0x380002c5, Rd_Rs,                s3_do16_dsp2},
798   {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
799   {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
800   {"msbl.fs!",  0x7e00,     0x7f00,     0x380000c4, Rd_Rs,                s3_do16_dsp2},
801   {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
802   {"msbu!",     0x7700,     0x7f00,     0x38000021, Rd_Rs,                s3_do16_dsp2},
803   {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
804   {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
805   {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
806   {"mszh.f!",   0x7d00,     0x7f00,     0x38000385, Rd_Rs,                s3_do16_dsp2},
807   {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
808   {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s3_do_dsp},
809   {"mszl.f!",   0x7c00,     0x7f00,     0x38000184, Rd_Rs,                s3_do16_dsp2},
810   {"mtcel!",    0x7000,     0x7ff0,     0x0000044a, x_Rs,                 s3_do16_dsp},
811   {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               s3_do_rd},
812   {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               s3_do_rd},
813   {"mtceh!",    0x7010,     0x7ff0,     0x0000084a, x_Rs,                 s3_do16_dsp},
814   {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
815   {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              s3_do_rdsrs},
816   {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
817   {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
818   {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
819   {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
820   {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
821   {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
822   {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              s3_do_rdcrs},
823   {"mul.f!",    0x7200,     0x7f00,     0x00000041, Rd_Rs,                s3_do16_dsp2},
824   {"mulu!",     0x7300,     0x7f00,     0x00000042, Rd_Rs,                s3_do16_dsp2},
825   {"mulr.l",    0x00000140, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
826   {"mulr.h",    0x00000240, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
827   {"mulr",      0x00000340, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
828   {"mulr.lf",   0x00000141, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
829   {"mulr.hf",   0x00000241, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
830   {"mulr.f",    0x00000341, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
831   {"mulur.l",   0x00000142, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
832   {"mulur.h",   0x00000242, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
833   {"mulur",     0x00000342, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
834   {"divr.q",    0x00000144, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
835   {"divr.r",    0x00000244, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
836   {"divr",      0x00000344, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
837   {"divur.q",   0x00000146, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
838   {"divur.r",   0x00000246, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
839   {"divur",     0x00000346, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_rdrsrs},
840   {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
841   {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
842   {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
843   {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
844   {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
845   {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
846   {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
847   {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
848   {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
849   {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
850   {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
851   {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
852   {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
853   {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
854
855   /* mv <-> mv!.  */
856   {"mv",        0x00003c56, 0x3e007fff, 0x4000,     Rd_Rs_x,              s3_do_rdrs},
857   {"mv!",       0x4000,     0x7c00,     0x8000,     Rd_Rs,                s3_do16_mv_cmp},
858   {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              s3_do_rdxrs},
859   {"neg.c",     0x0000001f, 0x3e0003ff, 0x8000,     Rd_x_Rs,              s3_do_rdxrs},
860   {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               s3_do_empty},
861   {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
862   {"not.c",     0x00000025, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s3_do_rdrs},
863   {"nop!",      0x0000,     0x7fff,     0x8000,     NO16_OPD,             s3_do_empty},
864   {"or",        0x00000022, 0x3e0003ff, 0x4a00,     Rd_Rs_Rs,             s3_do_rdrsrs},
865   {"or.c",      0x00000023, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
866   {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
867   {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
868   {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
869   {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               s3_do_rdi16},
870   {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            s3_do_rdrsi14},
871   {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            s3_do_rdrsi14},
872
873   /* or.c <-> or!.  */
874   {"or!",       0x4a00,     0x7f00,     0x8000,     Rd_Rs,                s3_do16_rdrs2},
875   {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               s3_do_empty},
876   {"pop!",      0x0040,     0x7fe0,     0x8000,     Rd_rvalueRs,          s3_do16_push_pop},
877   {"push!",     0x0060,     0x7fe0,     0x8000,     Rd_lvalueRs,          s3_do16_push_pop},
878
879   {"rpop!",     0x6800,     0x7c00,     0x8000,     Rd_I5,                s3_do16_rpop},
880   {"rpush!",    0x6c00,     0x7c00,     0x8000,     Rd_I5,                s3_do16_rpush},
881
882   {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
883   {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
884   {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
885   {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
886   {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
887   {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
888   {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
889   {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
890   {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
891   {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
892   {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
893   {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
894   {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               s3_do_empty},
895   {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        s3_do_ldst_atomic},
896   {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    s3_do_ldst_unalign},
897   {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    s3_do_ldst_unalign},
898   {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     s3_do_ldst_unalign},
899   {"sdbbp",     0x00000006, 0x3e0003ff, 0x0020,     x_I5_x,               s3_do_xi5x},
900   {"sdbbp!",    0x0020,     0x7fe0,     0x8000,     Rd_I5,                s3_do16_xi5},
901   {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               s3_do_empty},
902   {"rti",       0x0c0000e4, 0x3e0003ff, 0x8000,     NO_OPD,               s3_do_empty},
903   {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
904   {"sll.c",     0x00000031, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
905   {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
906   {"slli",      0x00000070, 0x3e0003ff, 0x5800,     Rd_Rs_I5,             s3_do_rdrsi5},
907   {"slli.c",    0x00000071, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
908
909   /* slli.c <-> slli!.  */
910   {"slli!",     0x5800,     0x7e00,     0x8000,     Rd_I5,                s3_do16_slli_srli},
911   {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
912   {"srl.c",     0x00000035, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
913   {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
914   {"sra.c",     0x00000037, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
915   {"srli",      0x00000074, 0x3e0003ff, 0x5a00,     Rd_Rs_I5,             s3_do_rdrsi5},
916   {"srli.c",    0x00000075, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
917   {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
918   {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s3_do_rdrsi5},
919
920   /* srli.c <-> srli!.  */
921   {"srli!",     0x5a00,     0x7e00,     0x8000,     Rd_Rs,                s3_do16_slli_srli},
922   {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s3_do_ldst_cop},
923   {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s3_do_ldst_cop},
924   {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s3_do_ldst_cop},
925   {"sub",       0x00000014, 0x3e0003ff, 0x4900,     Rd_Rs_Rs,             s3_do_rdrsrs},
926   {"sub.c",     0x00000015, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
927   {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_dsp2},
928   {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
929   {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
930
931   /* sub.c <-> sub!.  */
932   {"sub!",      0x4900,     0x7f00,     0x8000,     Rd_Rs,                s3_do16_rdrs2},
933   {"sw!",       0x2000,     0x7000,     0x8000,     Rd_lvalueRs,          s3_do16_ldst_insn},
934   {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  s3_do_i15},
935   {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
936   {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
937   {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
938   {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
939   {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
940   {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
941   {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
942   {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
943   {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
944   {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
945   {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
946   {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
947   {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
948   {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
949   {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               s3_do_xi5x},
950   {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
951   {"xor.c",     0x00000027, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s3_do_rdrsrs},
952
953   /* Macro instruction.  */
954   {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        s3_do_macro_li_rdi32},
955
956   /* la reg, imm32        -->(1)  ldi  reg, simm16
957                              (2)  ldis reg, %HI(imm32)
958                                   ori  reg, %LO(imm32)
959
960      la reg, symbol       -->(1)  lis  reg, %HI(imm32)
961                                   ori  reg, %LO(imm32)  */
962   {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        s3_do_macro_la_rdi32},
963   {"bcmpeqz",       0x0000004c, 0x3e00007e, 0x8000,     Insn_BCMP,        s3_do_macro_bcmpz},
964   {"bcmpeq",       0x0000004c, 0x3e00007e, 0x8000,     Insn_BCMP,        s3_do_macro_bcmp},
965   {"bcmpnez",       0x0000004e, 0x3e00007e, 0x8000,     Insn_BCMP,        s3_do_macro_bcmpz},
966   {"bcmpne",       0x0000004e, 0x3e00007e, 0x8000,     Insn_BCMP,        s3_do_macro_bcmp},
967   {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
968   {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
969   {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
970   {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
971   {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
972   {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
973   {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
974   {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
975   {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
976   {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s3_do_macro_mul_rdrsrs},
977   {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
978   {"lbu",       INSN_LBU,   0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
979   {"lh",        INSN_LH,    0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
980   {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
981   {"lw",        INSN_LW,    0x00000000, 0x1000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
982   {"sb",        INSN_SB,    0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
983   {"sh",        INSN_SH,    0x00000000, 0x8000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
984   {"sw",        INSN_SW,    0x00000000, 0x2000,     Insn_Type_SYN,        s3_do_macro_ldst_label},
985
986   /* Assembler use internal.  */
987   {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, s3_do_macro_rdi32hi},
988   {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, s3_do_macro_rdi32lo},
989   {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, s3_do_rdi16_pic},
990   {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, s3_do_addi_s_pic},
991   {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, s3_do_addi_u_pic},
992   {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, s3_do_lw_pic},
993
994   /* 48-bit instructions.  */
995   {"sdbbp48",   0x000000000000LL,   0x1c000000001fLL,   0x8000,     Rd_I32,    s3_do_sdbbp48},
996   {"ldi48",     0x000000000001LL,   0x1c000000001fLL,   0x8000,     Rd_I32,    s3_do_ldi48},
997   {"lw48",      0x000000000002LL,   0x1c000000001fLL,   0x8000,     Rd_I30,    s3_do_lw48},
998   {"sw48",      0x000000000003LL,   0x1c000000001fLL,   0x8000,     Rd_I30,    s3_do_sw48},
999   {"andri48",   0x040000000000LL,   0x1c0000000003LL,   0x8000,     Rd_I32,    s3_do_and48},
1000   {"andri48.c", 0x040000000001LL,   0x1c0000000003LL,   0x8000,     Rd_I32,    s3_do_and48},
1001   {"orri48",    0x040000000002LL,   0x1c0000000003LL,   0x8000,     Rd_I32,    s3_do_or48},
1002   {"orri48.c",  0x040000000003LL,   0x1c0000000003LL,   0x8000,     Rd_I32,    s3_do_or48},
1003 };
1004
1005 #define s3_SCORE3_PIPELINE 3
1006
1007 static int s3_university_version = 0;
1008 static int s3_vector_size = s3_SCORE3_PIPELINE;
1009 static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE];
1010
1011 static int s3_score3d = 1;
1012
1013 static int
1014 s3_end_of_line (char *str)
1015 {
1016   int retval = s3_SUCCESS;
1017
1018   s3_skip_whitespace (str);
1019   if (*str != '\0')
1020     {
1021       retval = (int) s3_FAIL;
1022
1023       if (!s3_inst.error)
1024         s3_inst.error = s3_BAD_GARBAGE;
1025     }
1026
1027   return retval;
1028 }
1029
1030 static int
1031 s3_score_reg_parse (char **ccp, struct hash_control *htab)
1032 {
1033   char *start = *ccp;
1034   char c;
1035   char *p;
1036   struct s3_reg_entry *reg;
1037
1038   p = start;
1039   if (!ISALPHA (*p) || !is_name_beginner (*p))
1040     return (int) s3_FAIL;
1041
1042   c = *p++;
1043
1044   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1045     c = *p++;
1046
1047   *--p = 0;
1048   reg = (struct s3_reg_entry *) hash_find (htab, start);
1049   *p = c;
1050
1051   if (reg)
1052     {
1053       *ccp = p;
1054       return reg->number;
1055     }
1056   return (int) s3_FAIL;
1057 }
1058
1059 /* If shift <= 0, only return reg.  */
1060
1061 static int
1062 s3_reg_required_here (char **str, int shift, enum s3_score_reg_type reg_type)
1063 {
1064   static char buff[s3_MAX_LITERAL_POOL_SIZE];
1065   int reg = (int) s3_FAIL;
1066   char *start = *str;
1067
1068   if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[reg_type].htab)) != (int) s3_FAIL)
1069     {
1070       if (reg_type == s3_REG_TYPE_SCORE)
1071         {
1072           if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
1073             {
1074               as_warn (_("Using temp register (r1)"));
1075               s3_inst.bwarn = 1;
1076             }
1077         }
1078       if (shift >= 0)
1079         {
1080           if (reg_type == s3_REG_TYPE_SCORE_CR)
1081             strcpy (s3_inst.reg, s3_score_crn_table[reg].name);
1082           else if (reg_type == s3_REG_TYPE_SCORE_SR)
1083             strcpy (s3_inst.reg, s3_score_srn_table[reg].name);
1084           else
1085             strcpy (s3_inst.reg, "");
1086
1087           s3_inst.instruction |= (bfd_vma) reg << shift;
1088         }
1089     }
1090   else
1091     {
1092       *str = start;
1093       sprintf (buff, _("register expected, not '%.100s'"), start);
1094       s3_inst.error = buff;
1095     }
1096
1097   return reg;
1098 }
1099
1100 static int
1101 s3_skip_past_comma (char **str)
1102 {
1103   char *p = *str;
1104   char c;
1105   int comma = 0;
1106
1107   while ((c = *p) == ' ' || c == ',')
1108     {
1109       p++;
1110       if (c == ',' && comma++)
1111         {
1112           s3_inst.error = s3_BAD_SKIP_COMMA;
1113           return (int) s3_FAIL;
1114         }
1115     }
1116
1117   if ((c == '\0') || (comma == 0))
1118     {
1119       s3_inst.error = s3_BAD_SKIP_COMMA;
1120       return (int) s3_FAIL;
1121     }
1122
1123   *str = p;
1124   return comma ? s3_SUCCESS : (int) s3_FAIL;
1125 }
1126
1127 static void
1128 s3_do_rdrsrs (char *str)
1129 {
1130   int reg;
1131   s3_skip_whitespace (str);
1132
1133   if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
1134       || s3_skip_past_comma (&str) == (int) s3_FAIL
1135       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1136       || s3_skip_past_comma (&str) == (int) s3_FAIL
1137       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1138       || s3_end_of_line (str) == (int) s3_FAIL)
1139     {
1140       return;
1141     }
1142   else
1143     {
1144       /* Check mulr, mulur rd is even number.  */
1145       if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
1146            || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
1147           && (reg % 2))
1148         {
1149           s3_inst.error = _("rd must be even number.");
1150           return;
1151         }
1152
1153       if ((((s3_inst.instruction >> 15) & 0x10) == 0)
1154           && (((s3_inst.instruction >> 10) & 0x10) == 0)
1155           && (((s3_inst.instruction >> 20) & 0x10) == 0)
1156           && (s3_inst.relax_inst != 0x8000)
1157           && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
1158         {
1159           s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
1160             | (((s3_inst.instruction >> 15) & 0xf) << 4);
1161           s3_inst.relax_size = 2;
1162         }
1163       else
1164         {
1165           s3_inst.relax_inst = 0x8000;
1166         }
1167     }
1168 }
1169
1170 static int
1171 s3_walk_no_bignums (symbolS * sp)
1172 {
1173   if (symbol_get_value_expression (sp)->X_op == O_big)
1174     return 1;
1175
1176   if (symbol_get_value_expression (sp)->X_add_symbol)
1177     return (s3_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1178             || (symbol_get_value_expression (sp)->X_op_symbol
1179                 && s3_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1180
1181   return 0;
1182 }
1183
1184 static int
1185 s3_my_get_expression (expressionS * ep, char **str)
1186 {
1187   char *save_in;
1188
1189   save_in = input_line_pointer;
1190   input_line_pointer = *str;
1191   s3_in_my_get_expression = 1;
1192   (void) expression (ep);
1193   s3_in_my_get_expression = 0;
1194
1195   if (ep->X_op == O_illegal)
1196     {
1197       *str = input_line_pointer;
1198       input_line_pointer = save_in;
1199       s3_inst.error = _("illegal expression");
1200       return (int) s3_FAIL;
1201     }
1202   /* Get rid of any bignums now, so that we don't generate an error for which
1203      we can't establish a line number later on.  Big numbers are never valid
1204      in instructions, which is where this routine is always called.  */
1205   if (ep->X_op == O_big
1206       || (ep->X_add_symbol
1207           && (s3_walk_no_bignums (ep->X_add_symbol)
1208               || (ep->X_op_symbol && s3_walk_no_bignums (ep->X_op_symbol)))))
1209     {
1210       s3_inst.error = _("invalid constant");
1211       *str = input_line_pointer;
1212       input_line_pointer = save_in;
1213       return (int) s3_FAIL;
1214     }
1215
1216   if ((ep->X_add_symbol != NULL)
1217       && (s3_inst.type != PC_DISP19div2)
1218       && (s3_inst.type != PC_DISP8div2)
1219       && (s3_inst.type != PC_DISP24div2)
1220       && (s3_inst.type != PC_DISP11div2)
1221       && (s3_inst.type != Insn_Type_SYN)
1222       && (s3_inst.type != Rd_rvalueRs_SI15)
1223       && (s3_inst.type != Rd_lvalueRs_SI15)
1224       && (s3_inst.type != Insn_internal)
1225       && (s3_inst.type != Rd_I30)
1226       && (s3_inst.type != Rd_I32)
1227       && (s3_inst.type != Insn_BCMP))
1228     {
1229       s3_inst.error = s3_BAD_ARGS;
1230       *str = input_line_pointer;
1231       input_line_pointer = save_in;
1232       return (int) s3_FAIL;
1233     }
1234
1235   *str = input_line_pointer;
1236   input_line_pointer = save_in;
1237   return s3_SUCCESS;
1238 }
1239
1240 /* Check if an immediate is valid.  If so, convert it to the right format.  */
1241 static bfd_signed_vma
1242 s3_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
1243 {
1244   switch (data_type)
1245     {
1246     case _VALUE_HI16:
1247       {
1248         bfd_signed_vma val_hi = ((val & 0xffff0000) >> 16);
1249
1250         if (s3_score_df_range[data_type].range[0] <= val_hi
1251             && val_hi <= s3_score_df_range[data_type].range[1])
1252           return val_hi;
1253       }
1254       break;
1255
1256     case _VALUE_LO16:
1257       {
1258         bfd_signed_vma val_lo = (val & 0xffff);
1259
1260         if (s3_score_df_range[data_type].range[0] <= val_lo
1261             && val_lo <= s3_score_df_range[data_type].range[1])
1262           return val_lo;
1263       }
1264       break;
1265
1266     case _SIMM14:
1267       if (hex_p == 1)
1268         {
1269           if (!(val >= -0x2000 && val <= 0x3fff))
1270             {
1271               return (int) s3_FAIL;
1272             }
1273         }
1274       else
1275         {
1276           if (!(val >= -8192 && val <= 8191))
1277             {
1278               return (int) s3_FAIL;
1279             }
1280         }
1281
1282       return val;
1283       break;
1284
1285     case _SIMM16_NEG:
1286       if (hex_p == 1)
1287         {
1288           if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1289             {
1290               return (int) s3_FAIL;
1291             }
1292         }
1293       else
1294         {
1295           if (!(val >= -32767 && val <= 32768))
1296             {
1297               return (int) s3_FAIL;
1298             }
1299         }
1300
1301       val = -val;
1302       return val;
1303       break;
1304
1305     case _IMM5_MULTI_LOAD:
1306       if (val >= 2 && val <= 32)
1307         {
1308           if (val == 32)
1309             val = 0;
1310           return val;
1311         }
1312       return (int) s3_FAIL;
1313
1314     case _IMM32:
1315       if (val >= 0 && val <= 0xffffffff)
1316         {
1317           return val;
1318         }
1319       else
1320         {
1321           return (int) s3_FAIL;
1322         }
1323
1324     default:
1325       if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1326         val = -val;
1327
1328       if (s3_score_df_range[data_type].range[0] <= val
1329           && val <= s3_score_df_range[data_type].range[1])
1330         return val;
1331
1332       break;
1333     }
1334
1335   return (int) s3_FAIL;
1336 }
1337
1338 static int
1339 s3_data_op2 (char **str, int shift, enum score_data_type data_type)
1340 {
1341   bfd_signed_vma value;
1342   char data_exp[s3_MAX_LITERAL_POOL_SIZE];
1343   char *dataptr;
1344   int cnt = 0;
1345   char *pp = NULL;
1346
1347   s3_skip_whitespace (*str);
1348   s3_inst.error = NULL;
1349   dataptr = * str;
1350
1351   /* Set hex_p to zero.  */
1352   int hex_p = 0;
1353
1354   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s3_MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
1355     {
1356       data_exp[cnt] = *dataptr;
1357       dataptr++;
1358       cnt++;
1359     }
1360
1361   data_exp[cnt] = '\0';
1362   pp = (char *)&data_exp;
1363
1364   if (*dataptr == '|')          /* process PCE */
1365     {
1366       if (s3_my_get_expression (&s3_inst.reloc.exp, &pp) == (int) s3_FAIL)
1367         return (int) s3_FAIL;
1368       s3_end_of_line (pp);
1369       if (s3_inst.error != 0)
1370         return (int) s3_FAIL;       /* to ouptut_inst to printf out the error */
1371       *str = dataptr;
1372     }
1373   else                          /* process  16 bit */
1374     {
1375       if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
1376         {
1377           return (int) s3_FAIL;
1378         }
1379
1380       dataptr = (char *)data_exp;
1381       for (; *dataptr != '\0'; dataptr++)
1382         {
1383           *dataptr = TOLOWER (*dataptr);
1384           if (*dataptr == '!' || *dataptr == ' ')
1385             break;
1386         }
1387       dataptr = (char *)data_exp;
1388
1389       if ((dataptr != NULL)
1390           && (((strstr (dataptr, "0x")) != NULL)
1391               || ((strstr (dataptr, "0X")) != NULL)))
1392         {
1393           hex_p = 1;
1394           if ((data_type != _SIMM16_LA)
1395               && (data_type != _VALUE_HI16)
1396               && (data_type != _VALUE_LO16)
1397               && (data_type != _IMM16)
1398               && (data_type != _IMM15)
1399               && (data_type != _IMM14)
1400               && (data_type != _IMM4)
1401               && (data_type != _IMM5)
1402               && (data_type != _IMM5_MULTI_LOAD)
1403               && (data_type != _IMM11)
1404               && (data_type != _IMM8)
1405               && (data_type != _IMM5_RSHIFT_1)
1406               && (data_type != _IMM5_RSHIFT_2)
1407               && (data_type != _SIMM14)
1408               && (data_type != _SIMM14_NEG)
1409               && (data_type != _SIMM16_NEG)
1410               && (data_type != _IMM10_RSHIFT_2)
1411               && (data_type != _GP_IMM15)
1412               && (data_type != _SIMM5)
1413               && (data_type != _SIMM6)
1414               && (data_type != _IMM32)
1415               && (data_type != _SIMM32))
1416             {
1417               data_type += 24;
1418             }
1419         }
1420
1421       if ((s3_inst.reloc.exp.X_add_number == 0)
1422           && (s3_inst.type != Insn_Type_SYN)
1423           && (s3_inst.type != Rd_rvalueRs_SI15)
1424           && (s3_inst.type != Rd_lvalueRs_SI15)
1425           && (s3_inst.type != Insn_internal)
1426           && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1427               || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1428               || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1429               || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1430         {
1431           s3_inst.error = s3_BAD_ARGS;
1432           return (int) s3_FAIL;
1433         }
1434     }
1435
1436   if ((s3_inst.reloc.exp.X_add_symbol)
1437       && ((data_type == _SIMM16)
1438           || (data_type == _SIMM16_NEG)
1439           || (data_type == _IMM16_NEG)
1440           || (data_type == _SIMM14)
1441           || (data_type == _SIMM14_NEG)
1442           || (data_type == _IMM5)
1443           || (data_type == _IMM5_MULTI_LOAD)
1444           || (data_type == _IMM11)
1445           || (data_type == _IMM14)
1446           || (data_type == _IMM20)
1447           || (data_type == _IMM16)
1448           || (data_type == _IMM15)
1449           || (data_type == _IMM4)))
1450     {
1451       s3_inst.error = s3_BAD_ARGS;
1452       return (int) s3_FAIL;
1453     }
1454
1455   if (s3_inst.reloc.exp.X_add_symbol)
1456     {
1457       switch (data_type)
1458         {
1459         case _SIMM16_LA:
1460           return (int) s3_FAIL;
1461         case _VALUE_HI16:
1462           s3_inst.reloc.type = BFD_RELOC_HI16_S;
1463           s3_inst.reloc.pc_rel = 0;
1464           break;
1465         case _VALUE_LO16:
1466           s3_inst.reloc.type = BFD_RELOC_LO16;
1467           s3_inst.reloc.pc_rel = 0;
1468           break;
1469         case _GP_IMM15:
1470           s3_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1471           s3_inst.reloc.pc_rel = 0;
1472           break;
1473         case _SIMM16_pic:
1474         case _IMM16_LO16_pic:
1475           s3_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1476           s3_inst.reloc.pc_rel = 0;
1477           break;
1478         default:
1479           s3_inst.reloc.type = BFD_RELOC_32;
1480           s3_inst.reloc.pc_rel = 0;
1481           break;
1482         }
1483     }
1484   else
1485     {
1486       if (data_type == _IMM16_pic)
1487         {
1488           s3_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1489           s3_inst.reloc.pc_rel = 0;
1490         }
1491
1492       if (data_type == _SIMM16_LA && s3_inst.reloc.exp.X_unsigned == 1)
1493         {
1494           value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
1495           if (value == (int) s3_FAIL)       /* for advance to check if this is ldis */
1496             if ((s3_inst.reloc.exp.X_add_number & 0xffff) == 0)
1497               {
1498                 s3_inst.instruction |= 0x8000000;
1499                 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1500                 return s3_SUCCESS;
1501               }
1502         }
1503       else
1504         {
1505           value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, hex_p);
1506         }
1507
1508       if (value == (int) s3_FAIL)
1509         {
1510           if (data_type == _IMM32)
1511             {
1512               sprintf (s3_err_msg,
1513                        _("invalid constant: %d bit expression not in range %u..%u"),
1514                        s3_score_df_range[data_type].bits,
1515                        0, (unsigned)0xffffffff);
1516             }
1517           else if (data_type == _IMM5_MULTI_LOAD)
1518             {
1519               sprintf (s3_err_msg,
1520                        _("invalid constant: %d bit expression not in range %u..%u"),
1521                        5, 2, 32);
1522             }
1523           else if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1524             {
1525               sprintf (s3_err_msg,
1526                        _("invalid constant: %d bit expression not in range %d..%d"),
1527                        s3_score_df_range[data_type].bits,
1528                        s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
1529             }
1530           else
1531             {
1532               sprintf (s3_err_msg,
1533                        _("invalid constant: %d bit expression not in range %d..%d"),
1534                        s3_score_df_range[data_type].bits,
1535                        -s3_score_df_range[data_type].range[1], -s3_score_df_range[data_type].range[0]);
1536             }
1537
1538           s3_inst.error = s3_err_msg;
1539           return (int) s3_FAIL;
1540         }
1541
1542       if (((s3_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1543           && data_type != _IMM5_MULTI_LOAD)
1544         {
1545           value &= (1 << s3_score_df_range[data_type].bits) - 1;
1546         }
1547
1548       s3_inst.instruction |= value << shift;
1549     }
1550
1551   if ((s3_inst.instruction & 0x3e000000) == 0x30000000)
1552     {
1553       if ((((s3_inst.instruction >> 20) & 0x1F) != 0)
1554           && (((s3_inst.instruction >> 20) & 0x1F) != 1)
1555           && (((s3_inst.instruction >> 20) & 0x1F) != 2)
1556           && (((s3_inst.instruction >> 20) & 0x1F) != 0x10))
1557         {
1558           s3_inst.error = _("invalid constant: bit expression not defined");
1559           return (int) s3_FAIL;
1560         }
1561     }
1562
1563   return s3_SUCCESS;
1564 }
1565
1566 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
1567 static void
1568 s3_do_rdsi16 (char *str)
1569 {
1570   s3_skip_whitespace (str);
1571
1572   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1573       || s3_skip_past_comma (&str) == (int) s3_FAIL
1574       || s3_data_op2 (&str, 1, _SIMM16) == (int) s3_FAIL
1575       || s3_end_of_line (str) == (int) s3_FAIL)
1576     return;
1577
1578   /* ldi.->ldiu! only for imm5  */
1579   if ((s3_inst.instruction & 0x20c0000) == 0x20c0000)
1580     {
1581       if  ((s3_inst.instruction & 0x1ffc0) != 0)
1582         {
1583           s3_inst.relax_inst = 0x8000;
1584         }
1585       else
1586         {
1587           s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
1588           s3_inst.relax_inst |= (((s3_inst.instruction >> 20)& 0x1f)  <<5);
1589           s3_inst.relax_size = 2;
1590         }
1591     }
1592   /*cmpi.c */
1593   else  if ((s3_inst.instruction & 0x02040001) == 0x02040001)
1594     {
1595       /*  imm <=0x3f  (5 bit<<1)*/
1596       if (((s3_inst.instruction & 0x1ffe0) == 0)
1597           || (((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)
1598               && (s3_inst.instruction & 0x003e) != 0))
1599         {
1600           s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
1601           s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5);
1602           s3_inst.relax_size = 2;
1603         }
1604       else
1605         {
1606           s3_inst.relax_inst =0x8000;
1607
1608         }
1609     }
1610   /* addi */
1611   else  if (((s3_inst.instruction & 0x2000000) == 0x02000000) && (s3_inst.relax_inst!=0x8000))
1612     {
1613       /* rd : 0-16 ; imm <=0x7f  (6 bit<<1)*/
1614       if ((((s3_inst.instruction >> 20) & 0x10) != 0x10)
1615           && (((s3_inst.instruction & 0x1ffc0) == 0)
1616               || (((s3_inst.instruction & 0x1ffc0) == 0x1ffc0)
1617                   && (s3_inst.instruction & 0x007e) != 0)))
1618         {
1619           s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
1620           s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
1621           s3_inst.relax_size = 2;
1622         }
1623       else
1624         {
1625           s3_inst.relax_inst =0x8000;
1626         }
1627     }
1628
1629   else if (((s3_inst.instruction >> 20) & 0x10) == 0x10)
1630     {
1631       s3_inst.relax_inst = 0x8000;
1632     }
1633 }
1634
1635 static void
1636 s3_do_ldis (char *str)
1637 {
1638   s3_skip_whitespace (str);
1639
1640   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1641       || s3_skip_past_comma (&str) == (int) s3_FAIL
1642       || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL
1643       || s3_end_of_line (str) == (int) s3_FAIL)
1644     return;
1645 }
1646
1647 /* Handle subi/subi.c.  */
1648 static void
1649 s3_do_sub_rdsi16 (char *str)
1650 {
1651   s3_skip_whitespace (str);
1652
1653   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1654       && s3_skip_past_comma (&str) != (int) s3_FAIL
1655       && s3_data_op2 (&str, 1, _SIMM16_NEG) != (int) s3_FAIL)
1656     s3_end_of_line (str);
1657 }
1658
1659 /* Handle subis/subis.c.  */
1660 static void
1661 s3_do_sub_rdi16 (char *str)
1662 {
1663   s3_skip_whitespace (str);
1664
1665   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1666       && s3_skip_past_comma (&str) != (int) s3_FAIL
1667       && s3_data_op2 (&str, 1, _IMM16_NEG) != (int) s3_FAIL)
1668     s3_end_of_line (str);
1669 }
1670
1671 /* Handle addri/addri.c.  */
1672 static void
1673 s3_do_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
1674 {
1675   s3_skip_whitespace (str);
1676
1677   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1678       && s3_skip_past_comma (&str) != (int) s3_FAIL
1679       && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1680       && s3_skip_past_comma (&str) != (int) s3_FAIL)
1681     s3_data_op2 (&str, 1, _SIMM14);
1682 }
1683
1684 /* Handle subri.c/subri.  */
1685 static void
1686 s3_do_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
1687 {
1688   s3_skip_whitespace (str);
1689
1690   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1691       && s3_skip_past_comma (&str) != (int) s3_FAIL
1692       && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1693       && s3_skip_past_comma (&str) != (int) s3_FAIL
1694       && s3_data_op2 (&str, 1, _SIMM14_NEG) != (int) s3_FAIL)
1695     s3_end_of_line (str);
1696 }
1697
1698 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.
1699    0~((2^14)-1) */
1700 static void
1701 s3_do_rdrsi5 (char *str)
1702 {
1703   s3_skip_whitespace (str);
1704
1705   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1706       || s3_skip_past_comma (&str) == (int) s3_FAIL
1707       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1708       || s3_skip_past_comma (&str) == (int) s3_FAIL
1709       || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL
1710       || s3_end_of_line (str) == (int) s3_FAIL)
1711     return;
1712
1713   if ((((s3_inst.instruction >> 20) & 0x1f) == ((s3_inst.instruction >> 15) & 0x1f))
1714       && (s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
1715     {
1716       s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f) ) | (((s3_inst.instruction >> 15) & 0xf) << 5);
1717       s3_inst.relax_size = 2;
1718     }
1719   else
1720     s3_inst.relax_inst = 0x8000;
1721 }
1722
1723 /* Handle andri/orri/andri.c/orri.c.
1724    0 ~ ((2^14)-1)  */
1725 static void
1726 s3_do_rdrsi14 (char *str)
1727 {
1728   s3_skip_whitespace (str);
1729
1730   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1731       && s3_skip_past_comma (&str) != (int) s3_FAIL
1732       && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1733       && s3_skip_past_comma (&str) != (int) s3_FAIL
1734       && s3_data_op2 (&str, 1, _IMM14) != (int) s3_FAIL)
1735     s3_end_of_line (str);
1736 }
1737
1738 /* Handle bittst.c.  */
1739 static void
1740 s3_do_xrsi5 (char *str)
1741 {
1742   s3_skip_whitespace (str);
1743
1744   if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1745       || s3_skip_past_comma (&str) == (int) s3_FAIL
1746       || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL
1747       || s3_end_of_line (str) == (int) s3_FAIL)
1748     return;
1749
1750   if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
1751     {
1752       s3_inst.relax_inst |= ((s3_inst.instruction >> 10) & 0x1f)  | (((s3_inst.instruction >> 15) & 0xf) << 5);
1753       s3_inst.relax_size = 2;
1754     }
1755   else
1756     s3_inst.relax_inst = 0x8000;
1757 }
1758
1759 /* Handle addis/andi/ori/andis/oris/ldis.  */
1760 static void
1761 s3_do_rdi16 (char *str)
1762 {
1763   s3_skip_whitespace (str);
1764
1765   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1766       || s3_skip_past_comma (&str) == (int) s3_FAIL
1767       || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL
1768       || s3_end_of_line (str) == (int) s3_FAIL)
1769     return;
1770
1771   /* ldis */
1772   if ((s3_inst.instruction & 0x3e0e0000) == 0x0a0c0000)
1773     {
1774       /* rd : 0-16 ;imm =0 -> can transform to addi!*/
1775       if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0))
1776         {
1777           s3_inst.relax_inst =0x5400; /* ldiu! */
1778           s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
1779           s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 5);
1780           s3_inst.relax_size = 2;
1781         }
1782       else
1783         {
1784           s3_inst.relax_inst =0x8000;
1785
1786         }
1787     }
1788
1789   /* addis */
1790   else if ((s3_inst.instruction & 0x3e0e0001) == 0x0a000000)
1791     {
1792       /* rd : 0-16 ;imm =0 -> can transform to addi!*/
1793       if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0))
1794         {
1795           s3_inst.relax_inst =0x5c00; /* addi! */
1796           s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
1797           s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
1798           s3_inst.relax_size = 2;
1799         }
1800       else
1801         {
1802           s3_inst.relax_inst =0x8000;
1803
1804         }
1805     }
1806 }
1807
1808 static void
1809 s3_do_macro_rdi32hi (char *str)
1810 {
1811   s3_skip_whitespace (str);
1812
1813   /* Do not handle s3_end_of_line().  */
1814   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1815       && s3_skip_past_comma (&str) != (int) s3_FAIL)
1816     s3_data_op2 (&str, 1, _VALUE_HI16);
1817 }
1818
1819 static void
1820 s3_do_macro_rdi32lo (char *str)
1821 {
1822   s3_skip_whitespace (str);
1823
1824   /* Do not handle s3_end_of_line().  */
1825   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1826       && s3_skip_past_comma (&str) != (int) s3_FAIL)
1827     s3_data_op2 (&str, 1, _VALUE_LO16);
1828 }
1829
1830 /* Handle ldis_pic.  */
1831 static void
1832 s3_do_rdi16_pic (char *str)
1833 {
1834   s3_skip_whitespace (str);
1835
1836   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1837       && s3_skip_past_comma (&str) != (int) s3_FAIL
1838       && s3_data_op2 (&str, 1, _IMM16_pic) != (int) s3_FAIL)
1839     s3_end_of_line (str);
1840 }
1841
1842 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
1843 static void
1844 s3_do_addi_s_pic (char *str)
1845 {
1846   s3_skip_whitespace (str);
1847
1848   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1849       && s3_skip_past_comma (&str) != (int) s3_FAIL
1850       && s3_data_op2 (&str, 1, _SIMM16_pic) != (int) s3_FAIL)
1851     s3_end_of_line (str);
1852 }
1853
1854 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
1855 static void
1856 s3_do_addi_u_pic (char *str)
1857 {
1858   s3_skip_whitespace (str);
1859
1860   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1861       && s3_skip_past_comma (&str) != (int) s3_FAIL
1862       && s3_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s3_FAIL)
1863     s3_end_of_line (str);
1864 }
1865
1866 /* Handle mfceh/mfcel/mtceh/mtchl.  */
1867 static void
1868 s3_do_rd (char *str)
1869 {
1870   s3_skip_whitespace (str);
1871
1872   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL)
1873     s3_end_of_line (str);
1874 }
1875
1876 /* Handle br{cond},cmpzteq.c ,cmpztmi.c ,cmpz.c */
1877 static void
1878 s3_do_rs (char *str)
1879 {
1880   s3_skip_whitespace (str);
1881
1882   if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1883       || s3_end_of_line (str) == (int) s3_FAIL)
1884     return;
1885
1886   if ((s3_inst.relax_inst != 0x8000) )
1887     {
1888       s3_inst.relax_inst |=  ((s3_inst.instruction >> 15) &0x1f);
1889       s3_inst.relax_size = 2;
1890     }
1891   else
1892     s3_inst.relax_inst = 0x8000;
1893 }
1894
1895 static void
1896 s3_do_i15 (char *str)
1897 {
1898   s3_skip_whitespace (str);
1899
1900   if (s3_data_op2 (&str, 10, _IMM15) != (int) s3_FAIL)
1901     s3_end_of_line (str);
1902 }
1903
1904 static void
1905 s3_do_xi5x (char *str)
1906 {
1907   s3_skip_whitespace (str);
1908
1909   if (s3_data_op2 (&str, 15, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
1910     return;
1911
1912   if (s3_inst.relax_inst != 0x8000)
1913     {
1914       s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f);
1915       s3_inst.relax_size = 2;
1916     }
1917 }
1918
1919 static void
1920 s3_do_rdrs (char *str)
1921 {
1922   s3_skip_whitespace (str);
1923
1924   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1925       || s3_skip_past_comma (&str) == (int) s3_FAIL
1926       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1927       || s3_end_of_line (str) == (int) s3_FAIL)
1928     return;
1929
1930   if (s3_inst.relax_inst != 0x8000)
1931     {
1932       if (((s3_inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv!*/
1933         {
1934           /* mv! rd : 5bit , ra : 5bit */
1935           s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f)  | (((s3_inst.instruction >> 20) & 0x1f) << 5);
1936           s3_inst.relax_size = 2;
1937         }
1938       else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
1939         {
1940           s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4)
1941             | (((s3_inst.instruction >> 20) & 0xf) << 8);
1942           s3_inst.relax_size = 2;
1943         }
1944       else
1945         {
1946           s3_inst.relax_inst = 0x8000;
1947         }
1948     }
1949 }
1950
1951 /* Handle mfcr/mtcr.  */
1952 static void
1953 s3_do_rdcrs (char *str)
1954 {
1955   s3_skip_whitespace (str);
1956
1957   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1958       && s3_skip_past_comma (&str) != (int) s3_FAIL
1959       && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) != (int) s3_FAIL)
1960     s3_end_of_line (str);
1961 }
1962
1963 /* Handle mfsr/mtsr.  */
1964 static void
1965 s3_do_rdsrs (char *str)
1966 {
1967   s3_skip_whitespace (str);
1968
1969   /* mfsr */
1970   if ((s3_inst.instruction & 0xff) == 0x50)
1971     {
1972       if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1973           && s3_skip_past_comma (&str) != (int) s3_FAIL
1974           && s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR) != (int) s3_FAIL)
1975         s3_end_of_line (str);
1976     }
1977   else
1978     {
1979       if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
1980           && s3_skip_past_comma (&str) != (int) s3_FAIL)
1981         s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR);
1982     }
1983 }
1984
1985 /* Handle neg.  */
1986 static void
1987 s3_do_rdxrs (char *str)
1988 {
1989   s3_skip_whitespace (str);
1990
1991   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1992       || s3_skip_past_comma (&str) == (int) s3_FAIL
1993       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1994       || s3_end_of_line (str) == (int) s3_FAIL)
1995     return;
1996
1997   if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 10) & 0x10) == 0)
1998       && (((s3_inst.instruction >> 20) & 0x10) == 0))
1999     {
2000       s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) << 4) | (((s3_inst.instruction >> 20) & 0xf) << 8);
2001       s3_inst.relax_size = 2;
2002     }
2003   else
2004     s3_inst.relax_inst = 0x8000;
2005 }
2006
2007 /* Handle cmp.c/cmp<cond>.  */
2008 static void
2009 s3_do_rsrs (char *str)
2010 {
2011   s3_skip_whitespace (str);
2012
2013   if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2014       || s3_skip_past_comma (&str) == (int) s3_FAIL
2015       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2016       || s3_end_of_line (str) == (int) s3_FAIL)
2017     return;
2018
2019   if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
2020     {
2021       s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
2022       s3_inst.relax_size = 2;
2023     }
2024   else
2025     s3_inst.relax_inst = 0x8000;
2026 }
2027
2028 static void
2029 s3_do_ceinst (char *str)
2030 {
2031   char *strbak;
2032
2033   strbak = str;
2034   s3_skip_whitespace (str);
2035
2036   if (s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL
2037       || s3_skip_past_comma (&str) == (int) s3_FAIL
2038       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2039       || s3_skip_past_comma (&str) == (int) s3_FAIL
2040       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2041       || s3_skip_past_comma (&str) == (int) s3_FAIL
2042       || s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL
2043       || s3_skip_past_comma (&str) == (int) s3_FAIL
2044       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
2045       || s3_end_of_line (str) == (int) s3_FAIL)
2046     {
2047       return;
2048     }
2049   else
2050     {
2051       str = strbak;
2052       if (s3_data_op2 (&str, 0, _IMM25) == (int) s3_FAIL)
2053         return;
2054     }
2055 }
2056
2057 static int
2058 s3_reglow_required_here (char **str, int shift)
2059 {
2060   static char buff[s3_MAX_LITERAL_POOL_SIZE];
2061   int reg;
2062   char *start = *str;
2063
2064   if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[s3_REG_TYPE_SCORE].htab)) != (int) s3_FAIL)
2065     {
2066       if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
2067         {
2068           as_warn (_("Using temp register(r1)"));
2069           s3_inst.bwarn = 1;
2070         }
2071       if (reg < 16)
2072         {
2073           if (shift >= 0)
2074             s3_inst.instruction |= (bfd_vma) reg << shift;
2075
2076           return reg;
2077         }
2078     }
2079
2080   /* Restore the start point, we may have got a reg of the wrong class.  */
2081   *str = start;
2082   sprintf (buff, _("low register (r0-r15) expected, not '%.100s'"), start);
2083   s3_inst.error = buff;
2084   return (int) s3_FAIL;
2085 }
2086
2087 /* Handle add!/and!/or!/sub!.  */
2088 static void
2089 s3_do16_rdrs2 (char *str)
2090 {
2091   s3_skip_whitespace (str);
2092
2093   if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
2094       || s3_skip_past_comma (&str) == (int) s3_FAIL
2095       || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
2096       || s3_end_of_line (str) == (int) s3_FAIL)
2097     {
2098       return;
2099     }
2100 }
2101
2102 /* Handle br!/brl!.  */
2103 static void
2104 s3_do16_br (char *str)
2105 {
2106   s3_skip_whitespace (str);
2107
2108   if (s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2109       || s3_end_of_line (str) == (int) s3_FAIL)
2110     {
2111       return;
2112     }
2113 }
2114
2115 /* Handle brr!.  */
2116 static void
2117 s3_do16_brr (char *str)
2118 {
2119   int rd = 0;
2120
2121   s3_skip_whitespace (str);
2122
2123   if ((rd = s3_reg_required_here (&str, 0,s3_REG_TYPE_SCORE)) == (int) s3_FAIL
2124       || s3_end_of_line (str) == (int) s3_FAIL)
2125     {
2126       return;
2127     }
2128 }
2129
2130 /*Handle ltbw / ltbh / ltbb */
2131 static void
2132 s3_do_ltb (char *str)
2133 {
2134   s3_skip_whitespace (str);
2135   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2136       || s3_skip_past_comma (&str) == (int) s3_FAIL)
2137     {
2138       return;
2139     }
2140
2141   s3_skip_whitespace (str);
2142   if (*str++ != '[')
2143     {
2144       s3_inst.error = _("missing [");
2145       return;
2146     }
2147
2148   if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2149       || s3_skip_past_comma (&str) == (int) s3_FAIL
2150       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
2151     {
2152       return;
2153     }
2154
2155   s3_skip_whitespace (str);
2156   if (*str++ != ']')
2157     {
2158       s3_inst.error = _("missing ]");
2159       return;
2160     }
2161 }
2162
2163 /* We need to be able to fix up arbitrary expressions in some statements.
2164    This is so that we can handle symbols that are an arbitrary distance from
2165    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
2166    which returns part of an address in a form which will be valid for
2167    a data instruction.  We do this by pushing the expression into a symbol
2168    in the expr_section, and creating a fix for that.  */
2169 static fixS *
2170 s3_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
2171 {
2172   fixS *new_fix;
2173
2174   switch (exp->X_op)
2175     {
2176     case O_constant:
2177     case O_symbol:
2178     case O_add:
2179     case O_subtract:
2180       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
2181       break;
2182     default:
2183       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
2184       break;
2185     }
2186   return new_fix;
2187 }
2188
2189 static void
2190 s3_init_dependency_vector (void)
2191 {
2192   int i;
2193
2194   for (i = 0; i < s3_vector_size; i++)
2195     memset (&s3_dependency_vector[i], '\0', sizeof (s3_dependency_vector[i]));
2196
2197   return;
2198 }
2199
2200 static enum s3_insn_type_for_dependency
2201 s3_dependency_type_from_insn (char *insn_name)
2202 {
2203   char name[s3_INSN_NAME_LEN];
2204   const struct s3_insn_to_dependency *tmp;
2205
2206   strcpy (name, insn_name);
2207   tmp = (const struct s3_insn_to_dependency *) hash_find (s3_dependency_insn_hsh, name);
2208
2209   if (tmp)
2210     return tmp->type;
2211
2212   return s3_D_all_insn;
2213 }
2214
2215 static int
2216 s3_check_dependency (char *pre_insn, char *pre_reg,
2217                      char *cur_insn, char *cur_reg, int *warn_or_error)
2218 {
2219   int bubbles = 0;
2220   unsigned int i;
2221   enum s3_insn_type_for_dependency pre_insn_type;
2222   enum s3_insn_type_for_dependency cur_insn_type;
2223
2224   pre_insn_type = s3_dependency_type_from_insn (pre_insn);
2225   cur_insn_type = s3_dependency_type_from_insn (cur_insn);
2226
2227   for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++)
2228     {
2229       if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type)
2230           && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type
2231               || cur_insn_type == s3_data_dependency_table[i].cur_insn_type)
2232           && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0
2233               || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0)
2234           && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0
2235               || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0))
2236         {
2237           bubbles = s3_data_dependency_table[i].bubblenum_3;
2238           *warn_or_error = s3_data_dependency_table[i].warn_or_error;
2239           break;
2240         }
2241     }
2242
2243   return bubbles;
2244 }
2245
2246 static void
2247 s3_build_one_frag (struct s3_score_it one_inst)
2248 {
2249   char *p;
2250   int relaxable_p = s3_g_opt;
2251   int relax_size = 0;
2252
2253   /* Start a new frag if frag_now is not empty.  */
2254   if (frag_now_fix () != 0)
2255     {
2256       if (!frag_now->tc_frag_data.is_insn)
2257         frag_wane (frag_now);
2258
2259       frag_new (0);
2260     }
2261   frag_grow (20);
2262
2263   p = frag_more (one_inst.size);
2264   s3_md_number_to_chars (p, one_inst.instruction, one_inst.size);
2265
2266 #ifdef OBJ_ELF
2267   dwarf2_emit_insn (one_inst.size);
2268 #endif
2269
2270   relaxable_p &= (one_inst.relax_size != 0);
2271   relax_size = relaxable_p ? one_inst.relax_size : 0;
2272
2273   p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2274                 s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2275                                  one_inst.type, 0, 0, relaxable_p),
2276                 NULL, 0, NULL);
2277
2278   if (relaxable_p)
2279     s3_md_number_to_chars (p, one_inst.relax_inst, relax_size);
2280 }
2281
2282 static void
2283 s3_handle_dependency (struct s3_score_it *theinst)
2284 {
2285   int i;
2286   int warn_or_error = 0;   /* warn - 0; error - 1  */
2287   int bubbles = 0;
2288   int remainder_bubbles = 0;
2289   char cur_insn[s3_INSN_NAME_LEN];
2290   char pre_insn[s3_INSN_NAME_LEN];
2291   struct s3_score_it nop_inst;
2292   struct s3_score_it pflush_inst;
2293
2294   nop_inst.instruction = 0x0000;
2295   nop_inst.size = 2;
2296   nop_inst.relax_inst = 0x80008000;
2297   nop_inst.relax_size = 4;
2298   nop_inst.type = NO16_OPD;
2299
2300   pflush_inst.instruction = 0x8000800a;
2301   pflush_inst.size = 4;
2302   pflush_inst.relax_inst = 0x8000;
2303   pflush_inst.relax_size = 0;
2304   pflush_inst.type = NO_OPD;
2305
2306   /* pflush will clear all data dependency.  */
2307   if (strcmp (theinst->name, "pflush") == 0)
2308     {
2309       s3_init_dependency_vector ();
2310       return;
2311     }
2312
2313   /* Push current instruction to s3_dependency_vector[0].  */
2314   for (i = s3_vector_size - 1; i > 0; i--)
2315     memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i]));
2316
2317   memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i]));
2318
2319   /* There is no dependency between nop and any instruction.  */
2320   if (strcmp (s3_dependency_vector[0].name, "nop") == 0
2321       || strcmp (s3_dependency_vector[0].name, "nop!") == 0)
2322     return;
2323
2324   strcpy (cur_insn, s3_dependency_vector[0].name);
2325
2326   for (i = 1; i < s3_vector_size; i++)
2327     {
2328       /* The element of s3_dependency_vector is NULL.  */
2329       if (s3_dependency_vector[i].name[0] == '\0')
2330         continue;
2331
2332       strcpy (pre_insn, s3_dependency_vector[i].name);
2333
2334       bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg,
2335                                      cur_insn, s3_dependency_vector[0].reg, &warn_or_error);
2336       remainder_bubbles = bubbles - i + 1;
2337
2338       if (remainder_bubbles > 0)
2339         {
2340           int j;
2341
2342           if (s3_fix_data_dependency == 1)
2343             {
2344               if (remainder_bubbles <= 2)
2345                 {
2346                   if (s3_warn_fix_data_dependency)
2347                     as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2348                              s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2349                              s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2350                              remainder_bubbles, bubbles);
2351
2352                   for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2353                     memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles],
2354                             sizeof (s3_dependency_vector[j]));
2355
2356                   for (j = 1; j <= remainder_bubbles; j++)
2357                     {
2358                       memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
2359                       /* Insert nop!.  */
2360                       s3_build_one_frag (nop_inst);
2361                     }
2362                 }
2363               else
2364                 {
2365                   if (s3_warn_fix_data_dependency)
2366                     as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2367                              s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2368                              s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2369                              bubbles);
2370
2371                   for (j = 1; j < s3_vector_size; j++)
2372                     memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
2373
2374                   /* Insert pflush.  */
2375                   s3_build_one_frag (pflush_inst);
2376                 }
2377             }
2378           else
2379             {
2380               if (warn_or_error)
2381                 {
2382                   as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2383                           s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2384                           s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2385                           remainder_bubbles, bubbles);
2386                 }
2387               else
2388                 {
2389                   as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2390                            s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2391                            s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2392                            remainder_bubbles, bubbles);
2393                 }
2394             }
2395         }
2396     }
2397 }
2398
2399 static enum insn_class
2400 s3_get_insn_class_from_type (enum score_insn_type type)
2401 {
2402   enum insn_class retval = (int) s3_FAIL;
2403
2404   switch (type)
2405     {
2406     case Rd_I4:
2407     case Rd_I5:
2408     case Rd_rvalueBP_I5:
2409     case Rd_lvalueBP_I5:
2410     case Rd_I8:
2411     case PC_DISP8div2:
2412     case PC_DISP11div2:
2413     case Rd_Rs:
2414     case Rd_HighRs:
2415     case Rd_lvalueRs:
2416     case Rd_rvalueRs:
2417     case x_Rs:
2418     case Rd_LowRs:
2419     case NO16_OPD:
2420     case Rd_SI5:
2421     case Rd_SI6:
2422       retval = INSN_CLASS_16;
2423       break;
2424     case Rd_Rs_I5:
2425     case x_Rs_I5:
2426     case x_I5_x:
2427     case Rd_Rs_I14:
2428     case I15:
2429     case Rd_I16:
2430     case Rd_SI16:
2431     case Rd_rvalueRs_SI10:
2432     case Rd_lvalueRs_SI10:
2433     case Rd_rvalueRs_preSI12:
2434     case Rd_rvalueRs_postSI12:
2435     case Rd_lvalueRs_preSI12:
2436     case Rd_lvalueRs_postSI12:
2437     case Rd_Rs_SI14:
2438     case Rd_rvalueRs_SI15:
2439     case Rd_lvalueRs_SI15:
2440     case PC_DISP19div2:
2441     case PC_DISP24div2:
2442     case Rd_Rs_Rs:
2443     case x_Rs_x:
2444     case x_Rs_Rs:
2445     case Rd_Rs_x:
2446     case Rd_x_Rs:
2447     case Rd_x_x:
2448     case OP5_rvalueRs_SI15:
2449     case I5_Rs_Rs_I5_OP5:
2450     case x_rvalueRs_post4:
2451     case Rd_rvalueRs_post4:
2452     case Rd_x_I5:
2453     case Rd_lvalueRs_post4:
2454     case x_lvalueRs_post4:
2455     case Rd_Rs_Rs_imm:
2456     case NO_OPD:
2457     case Rd_lvalue32Rs:
2458     case Rd_rvalue32Rs:
2459     case Insn_GP:
2460     case Insn_PIC:
2461     case Insn_internal:
2462     case Insn_BCMP:
2463     case Ra_I9_I5:
2464       retval = INSN_CLASS_32;
2465       break;
2466     case Insn_Type_PCE:
2467       retval = INSN_CLASS_PCE;
2468       break;
2469     case Insn_Type_SYN:
2470       retval = INSN_CLASS_SYN;
2471       break;
2472     case Rd_I30:
2473     case Rd_I32:
2474       retval = INSN_CLASS_48;
2475       break;
2476     default:
2477       abort ();
2478       break;
2479     }
2480   return retval;
2481 }
2482
2483 /* Type of p-bits:
2484    48-bit instruction: 1, 1, 0.
2485    32-bit instruction: 1, 0.
2486    16-bit instruction: 0.  */
2487 static bfd_vma
2488 s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class)
2489 {
2490   bfd_vma result = 0;
2491   bfd_vma m_code_high = 0;
2492   unsigned long m_code_middle = 0;
2493   unsigned long m_code_low = 0;
2494   bfd_vma pb_high = 0;
2495   unsigned long pb_middle = 0;
2496   unsigned long pb_low = 0;
2497
2498   if (i_class == INSN_CLASS_48)
2499     {
2500       pb_high = 0x800000000000LL;
2501       pb_middle = 0x80000000;
2502       pb_low = 0x00000000;
2503       m_code_high = m_code & 0x1fffc0000000LL;
2504       m_code_middle = m_code & 0x3fff8000;
2505       m_code_low = m_code & 0x00007fff;
2506       result = pb_high | (m_code_high << 2) |
2507         pb_middle | (m_code_middle << 1) |
2508         pb_low | m_code_low;
2509     }
2510   else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN)
2511     {
2512       pb_high = 0x80000000;
2513       pb_low = 0x00000000;
2514       m_code_high = m_code & 0x3fff8000;
2515       m_code_low = m_code & 0x00007fff;
2516       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2517     }
2518   else if (i_class == INSN_CLASS_16)
2519     {
2520       pb_high = 0;
2521       pb_low = 0;
2522       m_code_high = m_code & 0x3fff8000;
2523       m_code_low = m_code & 0x00007fff;
2524       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2525     }
2526   else if (i_class == INSN_CLASS_PCE)
2527     {
2528       /* Keep original.  */
2529       pb_high = 0;
2530       pb_low = 0x00008000;
2531       m_code_high = m_code & 0x3fff8000;
2532       m_code_low = m_code & 0x00007fff;
2533       result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2534     }
2535   else
2536     {
2537       abort ();
2538     }
2539
2540   return result;
2541 }
2542
2543 static void
2544 s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2)
2545 {
2546   char *p;
2547   bfd_boolean pce_p = FALSE;
2548   int relaxable_p = s3_g_opt;
2549   int relax_size = 0;
2550   struct s3_score_it *inst1 = part_1;
2551   struct s3_score_it *inst2 = part_2;
2552   struct s3_score_it backup_inst1;
2553
2554   pce_p = (inst2) ? TRUE : FALSE;
2555   memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it));
2556
2557   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
2558   if (pce_p)
2559     {
2560       backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2561         | (inst2->instruction & 0x7FFF);
2562       backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2563       backup_inst1.relax_inst = 0x8000;
2564       backup_inst1.size = s3_INSN_SIZE;
2565       backup_inst1.relax_size = 0;
2566       backup_inst1.type = Insn_Type_PCE;
2567     }
2568   else
2569     {
2570       backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction,
2571                                                       s3_GET_INSN_CLASS (backup_inst1.type));
2572     }
2573
2574   if (backup_inst1.relax_size != 0)
2575     {
2576       enum insn_class tmp;
2577
2578       tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2579       backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp);
2580     }
2581
2582   /* Check data dependency.  */
2583   s3_handle_dependency (&backup_inst1);
2584
2585   /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2586      data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
2587   if (frag_now_fix () != 0)
2588     {
2589       if (!frag_now->tc_frag_data.is_insn)
2590         frag_wane (frag_now);
2591
2592       frag_new (0);
2593     }
2594
2595   /* Here, we must call frag_grow in order to keep the instruction frag type is
2596      rs_machine_dependent.
2597      For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2598      actually will call frag_wane.
2599      Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2600      for frag_var.  */
2601   frag_grow (20);
2602
2603   p = frag_more (backup_inst1.size);
2604   s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2605
2606 #ifdef OBJ_ELF
2607   dwarf2_emit_insn (backup_inst1.size);
2608 #endif
2609
2610   /* Generate fixup structure.  */
2611   if (pce_p)
2612     {
2613       if (inst1->reloc.type != BFD_RELOC_NONE)
2614         s3_fix_new_score (frag_now, p - frag_now->fr_literal,
2615                           inst1->size, &inst1->reloc.exp,
2616                           inst1->reloc.pc_rel, inst1->reloc.type);
2617
2618       if (inst2->reloc.type != BFD_RELOC_NONE)
2619         s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2620                           inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2621     }
2622   else
2623     {
2624       if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2625         s3_fix_new_score (frag_now, p - frag_now->fr_literal,
2626                           backup_inst1.size, &backup_inst1.reloc.exp,
2627                           backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2628     }
2629
2630   /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
2631   relaxable_p &= (backup_inst1.relax_size != 0);
2632   relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2633
2634   p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2635                 s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2636                                  backup_inst1.type, 0, 0, relaxable_p),
2637                 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2638
2639   if (relaxable_p)
2640     s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2641
2642   memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it));
2643 }
2644
2645 static void
2646 s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2647 {
2648   char c;
2649   char *p;
2650   char *operator = insnstr;
2651   const struct s3_asm_opcode *opcode;
2652
2653   /* Parse operator and operands.  */
2654   s3_skip_whitespace (operator);
2655
2656   for (p = operator; *p != '\0'; p++)
2657     if ((*p == ' ') || (*p == '!'))
2658       break;
2659
2660   if (*p == '!')
2661     p++;
2662
2663   c = *p;
2664   *p = '\0';
2665
2666   opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
2667   *p = c;
2668
2669   memset (&s3_inst, '\0', sizeof (s3_inst));
2670   sprintf (s3_inst.str, "%s", insnstr);
2671   if (opcode)
2672     {
2673       s3_inst.instruction = opcode->value;
2674       s3_inst.relax_inst = opcode->relax_value;
2675       s3_inst.type = opcode->type;
2676       s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2677       s3_inst.relax_size = 0;
2678       s3_inst.bwarn = 0;
2679       sprintf (s3_inst.name, "%s", opcode->template_name);
2680       strcpy (s3_inst.reg, "");
2681       s3_inst.error = NULL;
2682       s3_inst.reloc.type = BFD_RELOC_NONE;
2683
2684       (*opcode->parms) (p);
2685
2686       /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1.  */
2687       if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2688         s3_gen_insn_frag (&s3_inst, NULL);
2689     }
2690   else
2691     s3_inst.error = _("unrecognized opcode");
2692 }
2693
2694 static void
2695 s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p)
2696 {
2697   char c;
2698   char *p;
2699   char *operator = insnstr;
2700   const struct s3_asm_opcode *opcode;
2701
2702   /* Parse operator and operands.  */
2703   s3_skip_whitespace (operator);
2704
2705   for (p = operator; *p != '\0'; p++)
2706     if (*p == ' ')
2707       break;
2708
2709   c = *p;
2710   *p = '\0';
2711
2712   opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
2713   *p = c;
2714
2715   memset (&s3_inst, '\0', sizeof (s3_inst));
2716   sprintf (s3_inst.str, "%s", insnstr);
2717   if (opcode)
2718     {
2719       s3_inst.instruction = opcode->value;
2720       s3_inst.relax_inst = opcode->relax_value;
2721       s3_inst.type = opcode->type;
2722       s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2723       s3_inst.relax_size = 0;
2724       s3_inst.bwarn = 0;
2725       sprintf (s3_inst.name, "%s", opcode->template_name);
2726       strcpy (s3_inst.reg, "");
2727       s3_inst.error = NULL;
2728       s3_inst.reloc.type = BFD_RELOC_NONE;
2729
2730       (*opcode->parms) (p);
2731
2732       /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1.  */
2733       if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2734         s3_gen_insn_frag (&s3_inst, NULL);
2735     }
2736   else
2737     s3_inst.error = _("unrecognized opcode");
2738 }
2739
2740 static int
2741 s3_append_insn (char *str, bfd_boolean gen_frag_p)
2742 {
2743   int retval = s3_SUCCESS;
2744
2745   s3_parse_16_32_inst (str, gen_frag_p);
2746
2747   if (s3_inst.error)
2748     {
2749       retval = (int) s3_FAIL;
2750       as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
2751       s3_inst.error = NULL;
2752     }
2753
2754   return retval;
2755 }
2756
2757 static void
2758 s3_do16_mv_cmp (char *str)
2759 {
2760   s3_skip_whitespace (str);
2761
2762   if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2763       || s3_skip_past_comma (&str) == (int) s3_FAIL
2764       || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2765       || s3_end_of_line (str) == (int) s3_FAIL)
2766     {
2767       return;
2768     }
2769 }
2770
2771 static void
2772 s3_do16_cmpi (char *str)
2773 {
2774   s3_skip_whitespace (str);
2775
2776   if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2777       || s3_skip_past_comma (&str) == (int) s3_FAIL
2778       || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL
2779       || s3_end_of_line (str) == (int) s3_FAIL)
2780     {
2781       return;
2782     }
2783 }
2784
2785 static void
2786 s3_do16_addi (char *str)
2787 {
2788   s3_skip_whitespace (str);
2789
2790   if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL
2791       || s3_skip_past_comma (&str) == (int) s3_FAIL
2792       || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL
2793       || s3_end_of_line (str) == (int) s3_FAIL)
2794     {
2795       return;
2796     }
2797 }
2798
2799 /* Handle bitclr! / bitset! / bittst! / bittgl! */
2800 static void
2801 s3_do16_rdi5 (char *str)
2802 {
2803   s3_skip_whitespace (str);
2804
2805   if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL
2806       || s3_skip_past_comma (&str) == (int) s3_FAIL
2807       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
2808       || s3_end_of_line (str) == (int) s3_FAIL)
2809     return;
2810   else
2811     {
2812       s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20)
2813         | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10);
2814       s3_inst.relax_size = 4;
2815     }
2816 }
2817
2818
2819 /* Handle sdbbp!.  */
2820 static void
2821 s3_do16_xi5 (char *str)
2822 {
2823   s3_skip_whitespace (str);
2824
2825   if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
2826     return;
2827 }
2828
2829 /* Check that an immediate is word alignment or half word alignment.
2830    If so, convert it to the right format.  */
2831 static int
2832 s3_validate_immediate_align (int val, unsigned int data_type)
2833 {
2834   if (data_type == _IMM5_RSHIFT_1)
2835     {
2836       if (val % 2)
2837         {
2838           s3_inst.error = _("address offset must be half word alignment");
2839           return (int) s3_FAIL;
2840         }
2841     }
2842   else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2843     {
2844       if (val % 4)
2845         {
2846           s3_inst.error = _("address offset must be word alignment");
2847           return (int) s3_FAIL;
2848         }
2849     }
2850
2851   return s3_SUCCESS;
2852 }
2853
2854 static int
2855 s3_exp_ldst_offset (char **str, int shift, unsigned int data_type)
2856 {
2857   char *dataptr;
2858
2859   dataptr = * str;
2860
2861   if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2862       && (data_type != _SIMM16_LA)
2863       && (data_type != _VALUE_HI16)
2864       && (data_type != _VALUE_LO16)
2865       && (data_type != _IMM16)
2866       && (data_type != _IMM15)
2867       && (data_type != _IMM14)
2868       && (data_type != _IMM4)
2869       && (data_type != _IMM5)
2870       && (data_type != _IMM8)
2871       && (data_type != _IMM5_RSHIFT_1)
2872       && (data_type != _IMM5_RSHIFT_2)
2873       && (data_type != _SIMM14_NEG)
2874       && (data_type != _IMM10_RSHIFT_2))
2875     {
2876       data_type += 24;
2877     }
2878
2879   if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
2880     return (int) s3_FAIL;
2881
2882   if (s3_inst.reloc.exp.X_op == O_constant)
2883     {
2884       /* Need to check the immediate align.  */
2885       int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type);
2886
2887       if (value == (int) s3_FAIL)
2888         return (int) s3_FAIL;
2889
2890       value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
2891       if (value == (int) s3_FAIL)
2892         {
2893           if (data_type < 30)
2894             sprintf (s3_err_msg,
2895                      _("invalid constant: %d bit expression not in range %d..%d"),
2896                      s3_score_df_range[data_type].bits,
2897                      s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
2898           else
2899             sprintf (s3_err_msg,
2900                      _("invalid constant: %d bit expression not in range %d..%d"),
2901                      s3_score_df_range[data_type - 24].bits,
2902                      s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]);
2903           s3_inst.error = s3_err_msg;
2904           return (int) s3_FAIL;
2905         }
2906
2907       if (data_type == _IMM5_RSHIFT_1)
2908         {
2909           value >>= 1;
2910         }
2911       else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2912         {
2913           value >>= 2;
2914         }
2915
2916       if (s3_score_df_range[data_type].range[0] != 0)
2917         {
2918           value &= (1 << s3_score_df_range[data_type].bits) - 1;
2919         }
2920
2921       s3_inst.instruction |= value << shift;
2922     }
2923   else
2924     {
2925       s3_inst.reloc.pc_rel = 0;
2926     }
2927
2928   return s3_SUCCESS;
2929 }
2930
2931 static void
2932 s3_do_ldst_insn (char *str)
2933 {
2934   int pre_inc = 0;
2935   int conflict_reg;
2936   int value;
2937   char * temp;
2938   char *dataptr;
2939   int reg;
2940   int ldst_idx = 0;
2941
2942   s3_skip_whitespace (str);
2943
2944   if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
2945       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
2946     return;
2947
2948   /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
2949   if (*str == '[')
2950     {
2951       str++;
2952       s3_skip_whitespace (str);
2953
2954       if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
2955         return;
2956
2957       /* Conflicts can occur on stores as well as loads.  */
2958       conflict_reg = (conflict_reg == reg);
2959       s3_skip_whitespace (str);
2960       temp = str + 1;    /* The latter will process decimal/hex expression.  */
2961
2962       /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
2963       if (*str == ']')
2964         {
2965           str++;
2966           if (*str == '+')
2967             {
2968               str++;
2969               /* ld/sw rD, [rA]+, simm12.  */
2970               if (s3_skip_past_comma (&str) == s3_SUCCESS)
2971                 {
2972                   if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL)
2973                       || (s3_end_of_line (str) == (int) s3_FAIL))
2974                     return;
2975
2976                   if (conflict_reg)
2977                     {
2978                       unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
2979
2980                       if ((ldst_func == INSN_LH)
2981                           || (ldst_func == INSN_LHU)
2982                           || (ldst_func == INSN_LW)
2983                           || (ldst_func == INSN_LB)
2984                           || (ldst_func == INSN_LBU))
2985                         {
2986                           s3_inst.error = _("register same as write-back base");
2987                           return;
2988                         }
2989                     }
2990
2991                   ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
2992                   s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2993                   s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2994
2995                   /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
2996                   if ((s3_inst.instruction & 0x3e000007) == 0x0e000000)
2997                     {
2998                       /* rs =  r0, offset = 4 */
2999                       if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3000                           && (((s3_inst.instruction >> 3) & 0xfff) == 4))
3001                         {
3002                           /* Relax to pop!.  */
3003                           s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f);
3004                           s3_inst.relax_size = 2;
3005                         }
3006                     }
3007                   return;
3008                 }
3009               /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
3010               else
3011                 {
3012                   s3_SET_INSN_ERROR (NULL);
3013                   if (s3_end_of_line (str) == (int) s3_FAIL)
3014                     {
3015                       return;
3016                     }
3017
3018                   pre_inc = 1;
3019                   value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0);
3020                   value &= (1 << s3_score_df_range[_SIMM12].bits) - 1;
3021                   ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3022                   s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3023                   s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3024                   s3_inst.instruction |= value << 3;
3025                   s3_inst.relax_inst = 0x8000;
3026                   return;
3027                 }
3028             }
3029           /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
3030           else
3031             {
3032               if (s3_end_of_line (str) == (int) s3_FAIL)
3033                 return;
3034
3035               ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3036               s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3037               s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3038
3039               /* lbu rd, [rs] -> lbu! rd, [rs]  */
3040               if (ldst_idx == INSN_LBU)
3041                 {
3042                   s3_inst.relax_inst = INSN16_LBU;
3043                 }
3044               else if (ldst_idx == INSN_LH)
3045                 {
3046                   s3_inst.relax_inst = INSN16_LH;
3047                 }
3048               else if (ldst_idx == INSN_LW)
3049                 {
3050                   s3_inst.relax_inst = INSN16_LW;
3051                 }
3052               else if (ldst_idx == INSN_SB)
3053                 {
3054                   s3_inst.relax_inst = INSN16_SB;
3055                 }
3056               else if (ldst_idx == INSN_SH)
3057                 {
3058                   s3_inst.relax_inst = INSN16_SH;
3059                 }
3060               else if (ldst_idx == INSN_SW)
3061                 {
3062                   s3_inst.relax_inst = INSN16_SW;
3063                 }
3064               else
3065                 {
3066                   s3_inst.relax_inst = 0x8000;
3067                 }
3068
3069               /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
3070               /* if ((ldst_idx == INSN_LBU)
3071                  || (ldst_idx == INSN_LH)
3072                  || (ldst_idx == INSN_LW)
3073                  || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/
3074               if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW))
3075                 {
3076                   /* ra only 3 bit , rd only 4 bit for lw! and sw! */
3077                   if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
3078                     {
3079                       s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) |
3080                         (((s3_inst.instruction >> 15) & 0x7) << 5);
3081                       s3_inst.relax_size = 2;
3082                     }
3083                 }
3084
3085               return;
3086             }
3087         }
3088       /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
3089       else
3090         {
3091           if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3092             {
3093               s3_inst.error = _("pre-indexed expression expected");
3094               return;
3095             }
3096
3097           if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3098             return;
3099
3100           s3_skip_whitespace (str);
3101           if (*str++ != ']')
3102             {
3103               s3_inst.error = _("missing ]");
3104               return;
3105             }
3106
3107           s3_skip_whitespace (str);
3108           /* ld/sw rD, [rA, simm12]+.  */
3109           if (*str == '+')
3110             {
3111               str++;
3112               pre_inc = 1;
3113               if (conflict_reg)
3114                 {
3115                   unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3116
3117                   if ((ldst_func == INSN_LH)
3118                       || (ldst_func == INSN_LHU)
3119                       || (ldst_func == INSN_LW)
3120                       || (ldst_func == INSN_LB)
3121                       || (ldst_func == INSN_LBU))
3122                     {
3123                       s3_inst.error = _("register same as write-back base");
3124                       return;
3125                     }
3126                 }
3127             }
3128
3129           if (s3_end_of_line (str) == (int) s3_FAIL)
3130             return;
3131
3132           if (s3_inst.reloc.exp.X_op == O_constant)
3133             {
3134               unsigned int data_type;
3135
3136               if (pre_inc == 1)
3137                 data_type = _SIMM12;
3138               else
3139                 data_type = _SIMM15;
3140               dataptr = temp;
3141
3142               if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
3143                   && (data_type != _SIMM16_LA)
3144                   && (data_type != _VALUE_HI16)
3145                   && (data_type != _VALUE_LO16)
3146                   && (data_type != _IMM16)
3147                   && (data_type != _IMM15)
3148                   && (data_type != _IMM14)
3149                   && (data_type != _IMM4)
3150                   && (data_type != _IMM5)
3151                   && (data_type != _IMM8)
3152                   && (data_type != _IMM5_RSHIFT_1)
3153                   && (data_type != _IMM5_RSHIFT_2)
3154                   && (data_type != _SIMM14_NEG)
3155                   && (data_type != _IMM10_RSHIFT_2))
3156                 {
3157                   data_type += 24;
3158                 }
3159
3160               value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3161               if (value == (int) s3_FAIL)
3162                 {
3163                   if (data_type < 30)
3164                     sprintf (s3_err_msg,
3165                              _("invalid constant: %d bit expression not in range %d..%d"),
3166                              s3_score_df_range[data_type].bits,
3167                              s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3168                   else
3169                     sprintf (s3_err_msg,
3170                              _("invalid constant: %d bit expression not in range %d..%d"),
3171                              s3_score_df_range[data_type - 24].bits,
3172                              s3_score_df_range[data_type - 24].range[0],
3173                              s3_score_df_range[data_type - 24].range[1]);
3174                   s3_inst.error = s3_err_msg;
3175                   return;
3176                 }
3177
3178               value &= (1 << s3_score_df_range[data_type].bits) - 1;
3179               ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3180               s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3181               s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3182               if (pre_inc == 1)
3183                 s3_inst.instruction |= value << 3;
3184               else
3185                 s3_inst.instruction |= value;
3186
3187               /* lw rD, [rA, simm15]  */
3188               if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
3189                 {
3190                   /*  rD  in [r0 - r15]. , ra in [r0-r7] */
3191                   if ((((s3_inst.instruction >> 15) & 0x18) == 0)
3192                       && (((s3_inst.instruction >> 20) & 0x10) == 0))
3193                     {
3194                       /* simm = [bit 7], lw -> lw!.  */
3195                       if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3196                         {
3197                           s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5)
3198                             | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3199                           s3_inst.relax_size = 2;
3200                         }
3201                       else
3202                         {
3203                           s3_inst.relax_inst = 0x8000;
3204                         }
3205                     }
3206                   else
3207                     {
3208                       s3_inst.relax_inst = 0x8000;
3209                     }
3210                 }
3211               /* sw rD, [rA, simm15]  */
3212               else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
3213                 {
3214                   /* rD is  in [r0 - r15] and ra in [r0-r7] */
3215                   if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
3216                     {
3217                       /* simm15 =7 bit  , sw -> sw!.  */
3218                       if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3219                         {
3220                           s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5)
3221                             | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3222                           s3_inst.relax_size = 2;
3223                         }
3224                       /* rA = r2, sw -> swp!.  */
3225                       else
3226                         {
3227                           s3_inst.relax_inst = 0x8000;
3228                         }
3229                     }
3230                   else
3231                     {
3232                       s3_inst.relax_inst = 0x8000;
3233                     }
3234                 }
3235               /* sw rD, [rA, simm15]+    sw pre.  */
3236               else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
3237                 {
3238                   /* simm15 = -4. and ra==r0 */
3239                   if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3240                       && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
3241                     {
3242                       /* sw -> push!.  */
3243                       s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
3244                       s3_inst.relax_size = 2;
3245                     }
3246                   else
3247                     {
3248                       s3_inst.relax_inst = 0x8000;
3249                     }
3250                 }
3251               else
3252                 {
3253                   s3_inst.relax_inst = 0x8000;
3254                 }
3255
3256               return;
3257             }
3258           else
3259             {
3260               /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3261               s3_inst.reloc.pc_rel = 0;
3262             }
3263         }
3264     }
3265   else
3266     {
3267       s3_inst.error = s3_BAD_ARGS;
3268     }
3269 }
3270
3271 /* Handle cache.  */
3272 static void
3273 s3_do_cache (char *str)
3274 {
3275   s3_skip_whitespace (str);
3276
3277   if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3278     {
3279       return;
3280     }
3281   else
3282     {
3283       int cache_op;
3284
3285       cache_op = (s3_inst.instruction >> 20) & 0x1F;
3286       sprintf (s3_inst.name, "cache %d", cache_op);
3287     }
3288
3289   if (*str == '[')
3290     {
3291       str++;
3292       s3_skip_whitespace (str);
3293
3294       if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3295         return;
3296
3297       s3_skip_whitespace (str);
3298
3299       /* cache op, [rA]  */
3300       if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3301         {
3302           s3_SET_INSN_ERROR (NULL);
3303           if (*str != ']')
3304             {
3305               s3_inst.error = _("missing ]");
3306               return;
3307             }
3308           str++;
3309         }
3310       /* cache op, [rA, simm15]  */
3311       else
3312         {
3313           if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
3314             {
3315               return;
3316             }
3317
3318           s3_skip_whitespace (str);
3319           if (*str++ != ']')
3320             {
3321               s3_inst.error = _("missing ]");
3322               return;
3323             }
3324         }
3325
3326       if (s3_end_of_line (str) == (int) s3_FAIL)
3327         return;
3328     }
3329   else
3330     {
3331       s3_inst.error = s3_BAD_ARGS;
3332     }
3333 }
3334
3335 static void
3336 s3_do_crdcrscrsimm5 (char *str)
3337 {
3338   char *strbak;
3339
3340   strbak = str;
3341   s3_skip_whitespace (str);
3342
3343   if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3344       || s3_skip_past_comma (&str) == (int) s3_FAIL
3345       || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3346       || s3_skip_past_comma (&str) == (int) s3_FAIL
3347       || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3348       || s3_skip_past_comma (&str) == (int) s3_FAIL)
3349     {
3350       str = strbak;
3351       /* cop1 cop_code20.  */
3352       if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
3353         return;
3354     }
3355   else
3356     {
3357       if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
3358         return;
3359     }
3360
3361   s3_end_of_line (str);
3362 }
3363
3364 /* Handle ldc/stc.  */
3365 static void
3366 s3_do_ldst_cop (char *str)
3367 {
3368   s3_skip_whitespace (str);
3369
3370   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL)
3371       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3372     return;
3373
3374   if (*str == '[')
3375     {
3376       str++;
3377       s3_skip_whitespace (str);
3378
3379       if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3380         return;
3381
3382       s3_skip_whitespace (str);
3383
3384       if (*str++ != ']')
3385         {
3386           if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
3387             return;
3388
3389           s3_skip_whitespace (str);
3390           if (*str++ != ']')
3391             {
3392               s3_inst.error = _("missing ]");
3393               return;
3394             }
3395         }
3396
3397       s3_end_of_line (str);
3398     }
3399   else
3400     s3_inst.error = s3_BAD_ARGS;
3401 }
3402
3403 static void
3404 s3_do16_ldst_insn (char *str)
3405 {
3406   int conflict_reg = 0;
3407   s3_skip_whitespace (str);
3408
3409   if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3410     return;
3411
3412   if (*str == '[')
3413     {
3414
3415       str++;
3416       s3_skip_whitespace (str);
3417
3418       if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
3419         return;
3420       if (conflict_reg&0x8)
3421         {
3422           sprintf (s3_err_msg,  _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
3423           s3_inst.error = s3_err_msg;
3424           return;
3425         }
3426
3427       s3_skip_whitespace (str);
3428
3429       if (*str == ']')
3430         {
3431           str++;
3432           if (s3_end_of_line (str) == (int) s3_FAIL)
3433             return;
3434         }
3435       else
3436         {
3437           if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3438             {
3439               s3_inst.error = _("comma is  expected");
3440               return;
3441             }
3442           if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3443             return;
3444           s3_skip_whitespace (str);
3445           if (*str++ != ']')
3446             {
3447               s3_inst.error = _("missing ]");
3448               return;
3449             }
3450           if (s3_end_of_line (str) == (int) s3_FAIL)
3451             return;
3452           if (s3_inst.reloc.exp.X_op == O_constant)
3453             {
3454               int value;
3455               unsigned int data_type;
3456               data_type = _IMM5_RSHIFT_2;
3457               value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3458               if (value == (int) s3_FAIL)
3459                 {
3460                   if (data_type < 30)
3461                     sprintf (s3_err_msg,
3462                              _("invalid constant: %d bit expression not in range %d..%d"),
3463                              s3_score_df_range[data_type].bits,
3464                              s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3465                   s3_inst.error = s3_err_msg;
3466                   return;
3467                 }
3468               if (value & 0x3)
3469                 {
3470                   sprintf (s3_err_msg,  _("invalid constant: %d is not word align integer"),value);
3471                   s3_inst.error = s3_err_msg;
3472                   return;
3473                 }
3474
3475               value >>= 2;
3476               s3_inst.instruction |= value;
3477             }
3478         }
3479     }
3480   else
3481     {
3482       sprintf (s3_err_msg,  _("missing ["));
3483       s3_inst.error = s3_err_msg;
3484       return;
3485     }
3486 }
3487
3488 static void
3489 s3_do_lw48 (char *str)
3490 {
3491   bfd_signed_vma val = 0;
3492
3493   s3_skip_whitespace (str);
3494
3495   if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3496       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3497     return;
3498
3499   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3500       || s3_end_of_line (str) == (int) s3_FAIL)
3501     {
3502       return;
3503     }
3504
3505   /* Check word align for lw48 rd, value.  */
3506   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3507       && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3508     {
3509       s3_inst.error = _("invalid constant: 32 bit expression not word align");
3510       return;
3511     }
3512
3513   /* Check and set offset.  */
3514   val = s3_inst.reloc.exp.X_add_number;
3515   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3516       && (!(val >= 0 && val <= 0xffffffffLL)))
3517     {
3518       s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3519       return;
3520     }
3521
3522   val &= 0xffffffff;
3523   val >>= 2;
3524   s3_inst.instruction |= (val << 7);
3525
3526   /* Set reloc type.  */
3527   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3528
3529 }
3530
3531 static void
3532 s3_do_sw48 (char *str)
3533 {
3534   bfd_signed_vma val = 0;
3535
3536   s3_skip_whitespace (str);
3537
3538   if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3539       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3540     return;
3541
3542   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3543       || s3_end_of_line (str) == (int) s3_FAIL)
3544     {
3545       return;
3546     }
3547
3548   /* Check word align for lw48 rd, value.  */
3549   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3550       && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3551     {
3552       s3_inst.error = _("invalid constant: 32 bit expression not word align");
3553       return;
3554     }
3555
3556   /* Check and set offset.  */
3557   val = s3_inst.reloc.exp.X_add_number;
3558   if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3559       && (!(val >= 0 && val <= 0xffffffffLL)))
3560     {
3561       s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3562       return;
3563     }
3564
3565   val &= 0xffffffff;
3566   val >>= 2;
3567   s3_inst.instruction |= (val << 7);
3568
3569   /* Set reloc type.  */
3570   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3571 }
3572
3573 static void
3574 s3_do_ldi48 (char *str)
3575 {
3576   bfd_signed_vma val;
3577
3578   s3_skip_whitespace (str);
3579
3580   if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL
3581       || s3_skip_past_comma (&str) == (int) s3_FAIL)
3582     return;
3583
3584   if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3585       || s3_end_of_line (str) == (int) s3_FAIL)
3586     {
3587       return;
3588     }
3589
3590   /* Check and set offset.  */
3591   val = s3_inst.reloc.exp.X_add_number;
3592   if (!(val >= -0xffffffffLL && val <= 0xffffffffLL))
3593     {
3594       s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]");
3595       return;
3596     }
3597
3598   val &= 0xffffffff;
3599   s3_inst.instruction |= (val << 5);
3600
3601   /* Set reloc type.  */
3602   s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32;
3603 }
3604
3605 static void
3606 s3_do_sdbbp48 (char *str)
3607 {
3608   s3_skip_whitespace (str);
3609
3610   if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
3611     return;
3612 }
3613
3614 static void
3615 s3_do_and48 (char *str)
3616 {
3617   s3_skip_whitespace (str);
3618
3619   if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3620       || s3_skip_past_comma (&str) == (int) s3_FAIL
3621       || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3622       || s3_skip_past_comma (&str) == (int) s3_FAIL
3623       || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3624       || s3_end_of_line (str) == (int) s3_FAIL)
3625     return;
3626 }
3627
3628 static void
3629 s3_do_or48 (char *str)
3630 {
3631   s3_skip_whitespace (str);
3632
3633   if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3634       || s3_skip_past_comma (&str) == (int) s3_FAIL
3635       || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3636       || s3_skip_past_comma (&str) == (int) s3_FAIL
3637       || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3638       || s3_end_of_line (str) == (int) s3_FAIL)
3639     return;
3640 }
3641
3642 static void
3643 s3_do_mbitclr (char *str)
3644 {
3645   int val;
3646   s3_skip_whitespace (str);
3647
3648   if (*str != '[')
3649     {
3650       sprintf (s3_err_msg,  _("missing ["));
3651       s3_inst.error = s3_err_msg;
3652       return;
3653     }
3654   str++;
3655
3656   s3_inst.instruction &= 0x0;
3657
3658   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3659       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3660       || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3661     return;
3662
3663   /* Get imm11 and refill opcode.  */
3664   val = s3_inst.instruction & 0x7ff;
3665   val >>= 2;
3666   s3_inst.instruction &= 0x000f8000;
3667   s3_inst.instruction |= 0x00000064;
3668
3669   if (*str != ']')
3670     {
3671       sprintf (s3_err_msg,  _("missing ]"));
3672       s3_inst.error = s3_err_msg;
3673       return;
3674     }
3675   str++;
3676
3677   if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3678       || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3679     return;
3680
3681   /* Set imm11 to opcode.  */
3682   s3_inst.instruction |= (val & 0x1)
3683     | (((val >> 1 ) & 0x7) << 7)
3684     | (((val >> 4 ) & 0x1f) << 20);
3685 }
3686
3687 static void
3688 s3_do_mbitset (char *str)
3689 {
3690   int val;
3691   s3_skip_whitespace (str);
3692
3693   if (*str != '[')
3694     {
3695       sprintf (s3_err_msg,  _("missing ["));
3696       s3_inst.error = s3_err_msg;
3697       return;
3698     }
3699   str++;
3700
3701   s3_inst.instruction &= 0x0;
3702
3703   if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3704       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3705       || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3706     return;
3707
3708   /* Get imm11 and refill opcode.  */
3709   val = s3_inst.instruction & 0x7ff;
3710   val >>= 2;
3711   s3_inst.instruction &= 0x000f8000;
3712   s3_inst.instruction |= 0x0000006c;
3713
3714   if (*str != ']')
3715     {
3716       sprintf (s3_err_msg,  _("missing ]"));
3717       s3_inst.error = s3_err_msg;
3718       return;
3719     }
3720   str++;
3721
3722   if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3723       || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3724     return;
3725
3726   /* Set imm11 to opcode.  */
3727   s3_inst.instruction |= (val & 0x1)
3728     | (((val >> 1 ) & 0x7) << 7)
3729     | (((val >> 4 ) & 0x1f) << 20);
3730 }
3731
3732 static void
3733 s3_do16_slli_srli (char *str)
3734 {
3735   s3_skip_whitespace (str);
3736
3737   if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL)
3738       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3739       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3740       || s3_end_of_line (str) == (int) s3_FAIL)
3741     return;
3742 }
3743
3744 static void
3745 s3_do16_ldiu (char *str)
3746 {
3747   s3_skip_whitespace (str);
3748
3749   if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3750       || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3751       || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3752       || s3_end_of_line (str) == (int) s3_FAIL)
3753     return;
3754 }
3755
3756 static void
3757 s3_do16_push_pop (char *str)
3758 {
3759   s3_skip_whitespace (str);
3760   if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
3761       || s3_end_of_line (str) == (int) s3_FAIL)
3762     return;
3763 }
3764
3765 static void
3766 s3_do16_rpush (char *str)
3767 {
3768   int reg;
3769   int val;
3770   s3_skip_whitespace (str);
3771   if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3772       || s3_skip_past_comma (&str) == (int) s3_FAIL
3773       || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3774       || s3_end_of_line (str) == (int) s3_FAIL)
3775     return;
3776
3777   /* 0: indicate 32.
3778      1: invalid value.
3779      2: to 31: normal value.  */
3780   val = s3_inst.instruction & 0x1f;
3781   if (val == 1)
3782     {
3783       s3_inst.error = _("imm5 should >= 2");
3784       return;
3785     }
3786   if (reg >= 32)
3787     {
3788       s3_inst.error = _("reg should <= 31");
3789       return;
3790     }
3791 }
3792
3793 static void
3794 s3_do16_rpop (char *str)
3795 {
3796   int reg;
3797   int val;
3798   s3_skip_whitespace (str);
3799   if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3800       || s3_skip_past_comma (&str) == (int) s3_FAIL
3801       || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3802       || s3_end_of_line (str) == (int) s3_FAIL)
3803     return;
3804
3805   /* 0: indicate 32.
3806      1: invalid value.
3807      2: to 31: normal value.  */
3808   val = s3_inst.instruction & 0x1f;
3809   if (val == 1)
3810     {
3811       s3_inst.error = _("imm5 should >= 2");
3812       return;
3813     }
3814
3815   if (reg >= 32)
3816     {
3817       s3_inst.error = _("reg should <= 31");
3818       return;
3819     }
3820   else
3821     {
3822       if ((reg + val) <= 32)
3823         reg = reg + val - 1;
3824       else
3825         reg = reg + val - 33;
3826       s3_inst.instruction &= 0x7c1f;
3827       s3_inst.instruction |= (reg << 5);
3828       return;
3829     }
3830 }
3831
3832 /* Handle lcb/lcw/lce/scb/scw/sce.  */
3833 static void
3834 s3_do_ldst_unalign (char *str)
3835 {
3836   int conflict_reg;
3837
3838   if (s3_university_version == 1)
3839     {
3840       s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3841       return;
3842     }
3843
3844   s3_skip_whitespace (str);
3845
3846   /* lcb/scb [rA]+.  */
3847   if (*str == '[')
3848     {
3849       str++;
3850       s3_skip_whitespace (str);
3851
3852       if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3853         return;
3854
3855       if (*str++ == ']')
3856         {
3857           if (*str++ != '+')
3858             {
3859               s3_inst.error = _("missing +");
3860               return;
3861             }
3862         }
3863       else
3864         {
3865           s3_inst.error = _("missing ]");
3866           return;
3867         }
3868
3869       if (s3_end_of_line (str) == (int) s3_FAIL)
3870         return;
3871     }
3872   /* lcw/lce/scb/sce rD, [rA]+.  */
3873   else
3874     {
3875       if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3876           || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3877         {
3878           return;
3879         }
3880
3881       s3_skip_whitespace (str);
3882       if (*str++ == '[')
3883         {
3884           int reg;
3885
3886           s3_skip_whitespace (str);
3887           if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3888             {
3889               return;
3890             }
3891
3892           /* Conflicts can occur on stores as well as loads.  */
3893           conflict_reg = (conflict_reg == reg);
3894           s3_skip_whitespace (str);
3895           if (*str++ == ']')
3896             {
3897               unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
3898
3899               if (*str++ == '+')
3900                 {
3901                   if (conflict_reg)
3902                     {
3903                       as_warn (_("%s register same as write-back base"),
3904                                ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3905                                 ? _("destination") : _("source")));
3906                     }
3907                 }
3908               else
3909                 {
3910                   s3_inst.error = _("missing +");
3911                   return;
3912                 }
3913
3914               if (s3_end_of_line (str) == (int) s3_FAIL)
3915                 return;
3916             }
3917           else
3918             {
3919               s3_inst.error = _("missing ]");
3920               return;
3921             }
3922         }
3923       else
3924         {
3925           s3_inst.error = s3_BAD_ARGS;
3926           return;
3927         }
3928     }
3929 }
3930
3931 /* Handle alw/asw.  */
3932 static void
3933 s3_do_ldst_atomic (char *str)
3934 {
3935   if (s3_university_version == 1)
3936     {
3937       s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3938       return;
3939     }
3940
3941   s3_skip_whitespace (str);
3942
3943   if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3944       || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3945     {
3946       return;
3947     }
3948   else
3949     {
3950
3951       s3_skip_whitespace (str);
3952       if (*str++ == '[')
3953         {
3954           int reg;
3955
3956           s3_skip_whitespace (str);
3957           if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3958             {
3959               return;
3960             }
3961
3962           s3_skip_whitespace (str);
3963           if (*str++ != ']')
3964             {
3965               s3_inst.error = _("missing ]");
3966               return;
3967             }
3968
3969           s3_end_of_line (str);
3970         }
3971       else
3972         s3_inst.error = s3_BAD_ARGS;
3973     }
3974 }
3975
3976 static void
3977 s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3978                      struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
3979                      symbolS *add_symbol)
3980 {
3981   int i;
3982   char *p;
3983   fixS *fixp = NULL;
3984   fixS *cur_fixp = NULL;
3985   long where;
3986   struct s3_score_it inst_main;
3987
3988   memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
3989
3990   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
3991   inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
3992   inst_main.type = Insn_PIC;
3993
3994   for (i = 0; i < var_num; i++)
3995     {
3996       inst_main.relax_size += var_insts[i].size;
3997       var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
3998                                                       s3_GET_INSN_CLASS (var_insts[i].type));
3999     }
4000
4001   /* Check data dependency.  */
4002   s3_handle_dependency (&inst_main);
4003
4004   /* Start a new frag if frag_now is not empty.  */
4005   if (frag_now_fix () != 0)
4006     {
4007       if (!frag_now->tc_frag_data.is_insn)
4008         {
4009           frag_wane (frag_now);
4010         }
4011       frag_new (0);
4012     }
4013   frag_grow (20);
4014
4015   /* Write fr_fix part.  */
4016   p = frag_more (inst_main.size);
4017   s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4018
4019   if (inst_main.reloc.type != BFD_RELOC_NONE)
4020     fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4021                              &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4022
4023   frag_now->tc_frag_data.fixp = fixp;
4024   cur_fixp = frag_now->tc_frag_data.fixp;
4025
4026 #ifdef OBJ_ELF
4027   dwarf2_emit_insn (inst_main.size);
4028 #endif
4029
4030   where = p - frag_now->fr_literal + inst_main.size;
4031   for (i = 0; i < var_num; i++)
4032     {
4033       if (i > 0)
4034         where += var_insts[i - 1].size;
4035
4036       if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4037         {
4038           fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
4039                                    &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4040                                    var_insts[i].reloc.type);
4041           if (fixp)
4042             {
4043               if (cur_fixp)
4044                 {
4045                   cur_fixp->fx_next = fixp;
4046                   cur_fixp = cur_fixp->fx_next;
4047                 }
4048               else
4049                 {
4050                   frag_now->tc_frag_data.fixp = fixp;
4051                   cur_fixp = frag_now->tc_frag_data.fixp;
4052                 }
4053             }
4054         }
4055     }
4056
4057   p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4058                 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4059                                  0, inst_main.size, 0), add_symbol, 0, NULL);
4060
4061   /* Write fr_var part.
4062      no calling s3_gen_insn_frag, no fixS will be generated.  */
4063   for (i = 0; i < var_num; i++)
4064     {
4065       s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4066       p += var_insts[i].size;
4067     }
4068   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4069   s3_inst.bwarn = -1;
4070 }
4071
4072 /* Build a relax frag for la instruction when generating s3_PIC,
4073    external symbol first and local symbol second.  */
4074 static void
4075 s3_build_la_pic (int reg_rd, expressionS exp)
4076 {
4077   symbolS *add_symbol = exp.X_add_symbol;
4078   offsetT add_number = exp.X_add_number;
4079   struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4080   struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4081   int fix_num = 0;
4082   int var_num = 0;
4083   char tmp[s3_MAX_LITERAL_POOL_SIZE];
4084   int r1_bak;
4085
4086   r1_bak = s3_nor1;
4087   s3_nor1 = 0;
4088
4089   if (add_number == 0)
4090     {
4091       fix_num = 1;
4092       var_num = 2;
4093
4094       /* For an external symbol, only one insn is generated;
4095          For a local symbol, two insns are generated.  */
4096       /* Fix part
4097          For an external symbol: lw rD, <sym>($gp)
4098          (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
4099       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4100       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4101         return;
4102
4103       if (reg_rd == s3_PIC_CALL_REG)
4104         s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4105       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4106
4107       /* Var part
4108          For a local symbol :
4109          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4110          addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4111       s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4112       memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4113       sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4114       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4115         return;
4116
4117       memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4118       s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4119     }
4120   else if (add_number >= -0x8000 && add_number <= 0x7fff)
4121     {
4122       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4123       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4124       if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4125         return;
4126
4127       /* Insn 2  */
4128       fix_num = 1;
4129       var_num = 1;
4130       /* Fix part
4131          For an external symbol: addi rD, <constant> */
4132       sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
4133       if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4134         return;
4135
4136       memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4137
4138       /* Var part
4139          For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
4140       sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (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, add_symbol->bsym->name);
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", add_symbol->bsym->name, 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", add_symbol->bsym->name);
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", add_symbol->bsym->name);
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_get_section_flags (stdoutput, 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_get_section_flags (stdoutput, 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 (stdoutput, 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 (stdoutput, 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_get_section_flags (stdoutput, 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_get_section_flags (stdoutput, 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 (stdoutput, bss_seg, SEC_ALLOC))
6137             as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6138 #endif
6139         }
6140     }
6141 #endif
6142
6143   SKIP_WHITESPACE ();
6144   if (*input_line_pointer == ',')
6145     {
6146       ++input_line_pointer;
6147       SKIP_WHITESPACE ();
6148
6149       if (is_end_of_line[(unsigned char)*input_line_pointer])
6150         {
6151           as_bad (_("missing alignment"));
6152           return;
6153         }
6154       else
6155         {
6156           align = get_absolute_expression ();
6157           needs_align = 1;
6158         }
6159     }
6160
6161   if (!needs_align)
6162     {
6163       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6164
6165       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6166       if (align)
6167         record_alignment (bss_seg, align);
6168     }
6169
6170   if (needs_align)
6171     {
6172       if (bytes_p)
6173         {
6174           /* Convert to a power of 2.  */
6175           if (align != 0)
6176             {
6177               unsigned int i;
6178
6179               for (i = 0; align != 0; align >>= 1, ++i)
6180                 ;
6181               align = i - 1;
6182             }
6183         }
6184
6185       if (align > max_alignment)
6186         {
6187           align = max_alignment;
6188           as_warn (_("alignment too large; %d assumed"), align);
6189         }
6190       else if (align < 0)
6191         {
6192           align = 0;
6193           as_warn (_("alignment negative; 0 assumed"));
6194         }
6195
6196       record_alignment (bss_seg, align);
6197     }
6198   else
6199     {
6200       /* Assume some objects may require alignment on some systems.  */
6201 #if defined (TC_ALPHA) && ! defined (VMS)
6202       if (temp > 1)
6203         {
6204           align = ffs (temp) - 1;
6205           if (temp % (1 << align))
6206             abort ();
6207         }
6208 #endif
6209     }
6210
6211   *p = 0;
6212   symbolP = symbol_find_or_make (name);
6213   *p = c;
6214
6215   if (
6216 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
6217 #ifdef BFD_ASSEMBLER
6218       (OUTPUT_FLAVOR != bfd_target_aout_flavour
6219        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6220 #else
6221       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6222 #endif
6223 #endif
6224       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6225     {
6226       char *pfrag;
6227
6228       subseg_set (bss_seg, 1);
6229
6230       if (align)
6231         frag_align (align, 0, 0);
6232
6233       /* Detach from old frag.  */
6234       if (S_GET_SEGMENT (symbolP) == bss_seg)
6235         symbol_get_frag (symbolP)->fr_symbol = NULL;
6236
6237       symbol_set_frag (symbolP, frag_now);
6238       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6239       *pfrag = 0;
6240
6241
6242       S_SET_SEGMENT (symbolP, bss_seg);
6243
6244 #ifdef OBJ_COFF
6245       /* The symbol may already have been created with a preceding
6246          ".globl" directive -- be careful not to step on storage class
6247          in that case.  Otherwise, set it to static.  */
6248       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6249         {
6250           S_SET_STORAGE_CLASS (symbolP, C_STAT);
6251         }
6252 #endif /* OBJ_COFF */
6253
6254 #ifdef S_SET_SIZE
6255       S_SET_SIZE (symbolP, temp);
6256 #endif
6257     }
6258   else
6259     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6260
6261   subseg_set (current_seg, current_subseg);
6262
6263   demand_empty_rest_of_line ();
6264 }
6265
6266 static void
6267 s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab)
6268 {
6269   int i = 0;
6270   int len = strlen (r->name) + 2;
6271   char *buf = XNEWVEC (char, len);
6272   char *buf2 = XNEWVEC (char, len);
6273
6274   strcpy (buf + i, r->name);
6275   for (i = 0; buf[i]; i++)
6276     {
6277       buf2[i] = TOUPPER (buf[i]);
6278     }
6279   buf2[i] = '\0';
6280
6281   hash_insert (htab, buf, (void *) r);
6282   hash_insert (htab, buf2, (void *) r);
6283 }
6284
6285 static void
6286 s3_build_reg_hsh (struct s3_reg_map *map)
6287 {
6288   const struct s3_reg_entry *r;
6289
6290   if ((map->htab = hash_new ()) == NULL)
6291     {
6292       as_fatal (_("virtual memory exhausted"));
6293     }
6294   for (r = map->names; r->name != NULL; r++)
6295     {
6296       s3_insert_reg (r, map->htab);
6297     }
6298 }
6299
6300 /* Iterate over the base tables to create the instruction patterns.  */
6301 static void
6302 s3_build_score_ops_hsh (void)
6303 {
6304   unsigned int i;
6305   static struct obstack insn_obstack;
6306
6307   obstack_begin (&insn_obstack, 4000);
6308   for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
6309     {
6310       const struct s3_asm_opcode *insn = s3_score_insns + i;
6311       size_t len = strlen (insn->template_name);
6312       struct s3_asm_opcode *new_opcode;
6313       char *template_name;
6314       new_opcode = (struct s3_asm_opcode *)
6315         obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
6316       template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
6317
6318       strcpy (template_name, insn->template_name);
6319       new_opcode->template_name = template_name;
6320       new_opcode->parms = insn->parms;
6321       new_opcode->value = insn->value;
6322       new_opcode->relax_value = insn->relax_value;
6323       new_opcode->type = insn->type;
6324       new_opcode->bitmask = insn->bitmask;
6325       hash_insert (s3_score_ops_hsh, new_opcode->template_name,
6326                    (void *) new_opcode);
6327     }
6328 }
6329
6330 static void
6331 s3_build_dependency_insn_hsh (void)
6332 {
6333   unsigned int i;
6334   static struct obstack dependency_obstack;
6335
6336   obstack_begin (&dependency_obstack, 4000);
6337   for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
6338     {
6339       const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
6340       size_t len = strlen (tmp->insn_name);
6341       struct s3_insn_to_dependency *new_i2n;
6342       char *buf;
6343
6344       new_i2n = (struct s3_insn_to_dependency *)
6345         obstack_alloc (&dependency_obstack,
6346                        sizeof (struct s3_insn_to_dependency));
6347       buf = (char *) obstack_alloc (&dependency_obstack, len + 1);
6348
6349       strcpy (buf, tmp->insn_name);
6350       new_i2n->insn_name = buf;
6351       new_i2n->type = tmp->type;
6352       hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name,
6353                    (void *) new_i2n);
6354     }
6355 }
6356
6357 static void
6358 s_score_bss (int ignore ATTRIBUTE_UNUSED)
6359 {
6360   if (score3)
6361     return s3_s_score_bss (ignore);
6362   else
6363     return s7_s_score_bss (ignore);
6364 }
6365
6366 static void
6367 s_score_text (int ignore)
6368 {
6369   if (score3)
6370     return s3_s_score_text (ignore);
6371   else
6372     return s7_s_score_text (ignore);
6373 }
6374
6375 static void
6376 s_section (int ignore)
6377 {
6378   if (score3)
6379     return s3_score_s_section (ignore);
6380   else
6381     return s7_s_section (ignore);
6382 }
6383
6384 static void
6385 s_change_sec (int sec)
6386 {
6387   if (score3)
6388     return s3_s_change_sec (sec);
6389   else
6390     return s7_s_change_sec (sec);
6391 }
6392
6393 static void
6394 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
6395 {
6396   if (score3)
6397     return s3_s_score_mask (reg_type);
6398   else
6399     return s7_s_score_mask (reg_type);
6400 }
6401
6402 static void
6403 s_score_ent (int aent)
6404 {
6405   if (score3)
6406     return s3_s_score_ent (aent);
6407   else
6408     return s7_s_score_ent (aent);
6409 }
6410
6411 static void
6412 s_score_frame (int ignore ATTRIBUTE_UNUSED)
6413 {
6414   if (score3)
6415     return s3_s_score_frame (ignore);
6416   else
6417     return s7_s_score_frame (ignore);
6418 }
6419
6420 static void
6421 s_score_end (int x ATTRIBUTE_UNUSED)
6422 {
6423   if (score3)
6424     return s3_s_score_end (x);
6425   else
6426     return s7_s_score_end (x);
6427 }
6428
6429 static void
6430 s_score_set (int x ATTRIBUTE_UNUSED)
6431 {
6432   if (score3)
6433     return s3_s_score_set (x);
6434   else
6435     return s7_s_score_set (x);
6436 }
6437
6438 static void
6439 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6440 {
6441   if (score3)
6442     return s3_s_score_cpload (ignore);
6443   else
6444     return s7_s_score_cpload (ignore);
6445 }
6446
6447 static void
6448 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6449 {
6450   if (score3)
6451     return s3_s_score_cprestore (ignore);
6452   else
6453     return s7_s_score_cprestore (ignore);
6454 }
6455
6456 static void
6457 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6458 {
6459   if (score3)
6460     return s3_s_score_gpword (ignore);
6461   else
6462     return s7_s_score_gpword (ignore);
6463 }
6464
6465 static void
6466 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6467 {
6468   if (score3)
6469     return s3_s_score_cpadd (ignore);
6470   else
6471     return s7_s_score_cpadd (ignore);
6472 }
6473
6474 static void
6475 s_score_lcomm (int bytes_p)
6476 {
6477   if (score3)
6478     return s3_s_score_lcomm (bytes_p);
6479   else
6480     return s7_s_score_lcomm (bytes_p);
6481 }
6482
6483 static void
6484 s3_assemble (char *str)
6485 {
6486   know (str);
6487   know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
6488
6489   memset (&s3_inst, '\0', sizeof (s3_inst));
6490   if (s3_INSN_IS_PCE_P (str))
6491     s3_parse_pce_inst (str);
6492   else if (s3_INSN_IS_48_P (str))
6493     s3_parse_48_inst (str, TRUE);
6494   else
6495     s3_parse_16_32_inst (str, TRUE);
6496
6497   if (s3_inst.error)
6498     as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
6499 }
6500
6501 static void
6502 s3_operand (expressionS * exp)
6503 {
6504   if (s3_in_my_get_expression)
6505     {
6506       exp->X_op = O_illegal;
6507       if (s3_inst.error == NULL)
6508         {
6509           s3_inst.error = _("bad expression");
6510         }
6511     }
6512 }
6513
6514 static void
6515 s3_begin (void)
6516 {
6517   unsigned int i;
6518   segT seg;
6519   subsegT subseg;
6520
6521   if ((s3_score_ops_hsh = hash_new ()) == NULL)
6522     as_fatal (_("virtual memory exhausted"));
6523
6524   s3_build_score_ops_hsh ();
6525
6526   if ((s3_dependency_insn_hsh = hash_new ()) == NULL)
6527     as_fatal (_("virtual memory exhausted"));
6528
6529   s3_build_dependency_insn_hsh ();
6530
6531   for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
6532     s3_build_reg_hsh (s3_all_reg_maps + i);
6533
6534   /* Initialize dependency vector.  */
6535   s3_init_dependency_vector ();
6536
6537   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6538   seg = now_seg;
6539   subseg = now_subseg;
6540   s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6541   (void)bfd_set_section_flags (stdoutput, s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6542   (void)bfd_set_section_alignment (stdoutput, s3_pdr_seg, 2);
6543   subseg_set (seg, subseg);
6544
6545   if (s3_USE_GLOBAL_POINTER_OPT)
6546     bfd_set_gp_size (stdoutput, s3_g_switch_value);
6547 }
6548
6549 static void
6550 s3_number_to_chars (char *buf, valueT val, int n)
6551 {
6552   if (target_big_endian)
6553     number_to_chars_bigendian (buf, val, n);
6554   else
6555     number_to_chars_littleendian (buf, val, n);
6556 }
6557
6558 static valueT
6559 s3_normal_chars_to_number (char *buf, int n)
6560 {
6561   valueT result = 0;
6562   unsigned char *where = (unsigned char *)buf;
6563
6564   if (target_big_endian)
6565     {
6566       while (n--)
6567         {
6568           result <<= 8;
6569           result |= (*where++ & 255);
6570         }
6571     }
6572   else
6573     {
6574       while (n--)
6575         {
6576           result <<= 8;
6577           result |= (where[n] & 255);
6578         }
6579     }
6580
6581   return result;
6582 }
6583
6584 static void
6585 s3_number_to_chars_littleendian (void *p, valueT data, int n)
6586 {
6587   char *buf = (char *) p;
6588
6589   switch (n)
6590     {
6591     case 4:
6592       md_number_to_chars (buf, data >> 16, 2);
6593       md_number_to_chars (buf + 2, data, 2);
6594       break;
6595     case 6:
6596       md_number_to_chars (buf, data >> 32, 2);
6597       md_number_to_chars (buf + 2, data >> 16, 2);
6598       md_number_to_chars (buf + 4, data, 2);
6599       break;
6600     default:
6601       /* Error routine.  */
6602       as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6603       break;
6604     }
6605 }
6606
6607 static valueT
6608 s3_chars_to_number_littleendian (const void *p, int n)
6609 {
6610   char *buf = (char *) p;
6611   valueT result = 0;
6612
6613   switch (n)
6614     {
6615     case 4:
6616       result =  s3_normal_chars_to_number (buf, 2) << 16;
6617       result |= s3_normal_chars_to_number (buf + 2, 2);
6618       break;
6619     case 6:
6620       result =  s3_normal_chars_to_number (buf, 2) << 32;
6621       result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
6622       result |= s3_normal_chars_to_number (buf + 4, 2);
6623       break;
6624     default:
6625       /* Error routine.  */
6626       as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6627       break;
6628     }
6629
6630   return result;
6631 }
6632
6633 static void
6634 s3_md_number_to_chars (char *buf, valueT val, int n)
6635 {
6636   if (!target_big_endian && n >= 4)
6637     s3_number_to_chars_littleendian (buf, val, n);
6638   else
6639     md_number_to_chars (buf, val, n);
6640 }
6641
6642 static valueT
6643 s3_md_chars_to_number (char *buf, int n)
6644 {
6645   valueT result = 0;
6646
6647   if (!target_big_endian && n >= 4)
6648     result = s3_chars_to_number_littleendian (buf, n);
6649   else
6650     result = s3_normal_chars_to_number (buf, n);
6651
6652   return result;
6653 }
6654
6655 static const char *
6656 s3_atof (int type, char *litP, int *sizeP)
6657 {
6658   int prec;
6659   LITTLENUM_TYPE words[s3_MAX_LITTLENUMS];
6660   char *t;
6661   int i;
6662
6663   switch (type)
6664     {
6665     case 'f':
6666     case 'F':
6667     case 's':
6668     case 'S':
6669       prec = 2;
6670       break;
6671     case 'd':
6672     case 'D':
6673     case 'r':
6674     case 'R':
6675       prec = 4;
6676       break;
6677     case 'x':
6678     case 'X':
6679     case 'p':
6680     case 'P':
6681       prec = 6;
6682       break;
6683     default:
6684       *sizeP = 0;
6685       return _("bad call to MD_ATOF()");
6686     }
6687
6688   t = atof_ieee (input_line_pointer, type, words);
6689   if (t)
6690     input_line_pointer = t;
6691   *sizeP = prec * 2;
6692
6693   if (target_big_endian)
6694     {
6695       for (i = 0; i < prec; i++)
6696         {
6697           s3_md_number_to_chars (litP, (valueT) words[i], 2);
6698           litP += 2;
6699         }
6700     }
6701   else
6702     {
6703       for (i = 0; i < prec; i += 2)
6704         {
6705           s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
6706           s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
6707           litP += 4;
6708         }
6709     }
6710
6711   return 0;
6712 }
6713
6714 static void
6715 s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6716 {
6717   know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
6718 }
6719
6720 static void
6721 s3_validate_fix (fixS *fixP)
6722 {
6723   fixP->fx_where += fixP->fx_frag->insn_addr;
6724 }
6725
6726 static int
6727 s3_force_relocation (struct fix *fixp)
6728 {
6729   int retval = 0;
6730
6731   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6732       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6733       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6734       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6735       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6736       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
6737       || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
6738     {
6739       retval = 1;
6740     }
6741   return retval;
6742 }
6743
6744 static bfd_boolean
6745 s3_fix_adjustable (fixS * fixP)
6746 {
6747   if (fixP->fx_addsy == NULL)
6748     {
6749       return 1;
6750     }
6751   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6752            && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6753     {
6754       return 0;
6755     }
6756   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6757            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6758            || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6759            || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6760     {
6761       return 0;
6762     }
6763
6764   return 1;
6765 }
6766
6767 static void
6768 s3_elf_final_processing (void)
6769 {
6770   unsigned long val = 0;
6771
6772   if (score3)
6773     val = E_SCORE_MACH_SCORE3;
6774   else if (score7)
6775     val = E_SCORE_MACH_SCORE7;
6776
6777   elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6778   elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6779   elf_elfheader (stdoutput)->e_flags |= val;
6780
6781   if (s3_fix_data_dependency == 1)
6782     {
6783       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6784     }
6785   if (s3_score_pic == s3_PIC)
6786     {
6787       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6788     }
6789 }
6790
6791 static int
6792 s3_judge_size_before_relax (fragS * fragp, asection *sec)
6793 {
6794   int change = 0;
6795
6796   if (s3_score_pic == s3_NO_PIC)
6797     change = s3_nopic_need_relax (fragp->fr_symbol, 0);
6798   else
6799     change = s3_pic_need_relax (fragp->fr_symbol, sec);
6800
6801   if (change == 1)
6802     {
6803       /* Only at the first time determining whether s3_GP instruction relax should be done,
6804          return the difference between instruction size and instruction relax size.  */
6805       if (fragp->fr_opcode == NULL)
6806         {
6807           fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
6808           fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6809           return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
6810         }
6811     }
6812
6813   return 0;
6814 }
6815
6816 static int
6817 s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
6818 {
6819   if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6820       || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6821     return s3_judge_size_before_relax (fragp, sec);
6822
6823   return 0;
6824 }
6825
6826 static int
6827 s3_relax_branch_inst32 (fragS * fragp)
6828 {
6829   fragp->fr_opcode = NULL;
6830   return 0;
6831 }
6832
6833 static int
6834 s3_relax_branch_inst16 (fragS * fragp)
6835 {
6836   int relaxable_p = 0;
6837   int frag_addr = fragp->fr_address + fragp->insn_addr;
6838   addressT symbol_address = 0;
6839   symbolS *s;
6840   offsetT offset;
6841   long value;
6842   unsigned long inst_value;
6843
6844   relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6845
6846   s = fragp->fr_symbol;
6847   if (s == NULL)
6848     frag_addr = 0;
6849   else
6850     {
6851       if (s->bsym != NULL)
6852         symbol_address = (addressT) symbol_get_frag (s)->fr_address;
6853     }
6854
6855   inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
6856   offset = (inst_value & 0x1ff) << 1;
6857   if ((offset & 0x200) == 0x200)
6858     offset |= 0xfffffc00;
6859
6860   value = offset + symbol_address - frag_addr;
6861
6862   if (relaxable_p
6863       && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6864       && fragp->fr_fix == 2
6865       && (s->bsym != NULL)
6866       && (S_IS_DEFINED (s)
6867           && !S_IS_COMMON (s)
6868           && !S_IS_EXTERNAL (s)))
6869     {
6870       /* Relax branch 32 to branch 16.  */
6871       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6872       fragp->fr_fix = 4;
6873       return 2;
6874     }
6875   else
6876     return 0;
6877 }
6878
6879 static int
6880 s3_relax_cmpbranch_inst32 (fragS * fragp)
6881 {
6882   int relaxable_p = 0;
6883   symbolS *s;
6884   /* For sign bit.  */
6885   long offset;
6886   long frag_addr = fragp->fr_address + fragp->insn_addr;
6887   long symbol_address = 0;
6888   long value;
6889   unsigned long inst_value;
6890
6891   relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6892
6893   s = fragp->fr_symbol;
6894   if (s == NULL)
6895     frag_addr = 0;
6896   else
6897     {
6898       if (s->bsym != NULL)
6899         symbol_address = (addressT) symbol_get_frag (s)->fr_address;
6900     }
6901
6902   inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
6903   offset = (inst_value & 0x1)
6904     | (((inst_value >> 7) & 0x7) << 1)
6905     | (((inst_value >> 21) & 0x1f) << 4);
6906   offset <<= 1;
6907   if ((offset & 0x200) == 0x200)
6908     offset |= 0xfffffe00;
6909
6910   value = offset + symbol_address - frag_addr;
6911   /* change the order of judging rule is because
6912      1.not defined symbol or common symbol or external symbol will change
6913      bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
6914      2.if the flow is as before : it will results to recursive loop
6915   */
6916   if (fragp->fr_fix == 6)
6917     {
6918       /* Have already relaxed!  Just return 0 to terminate the loop.  */
6919       return 0;
6920     }
6921   /* need to translate when extern or not defined or common symbol */
6922   else if ((relaxable_p
6923             && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6924             && fragp->fr_fix == 4
6925             && (s->bsym != NULL))
6926            || !S_IS_DEFINED (s)
6927            ||S_IS_COMMON (s)
6928            ||S_IS_EXTERNAL (s))
6929     {
6930       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6931       fragp->fr_fix = 6;
6932       return 2;
6933     }
6934   else
6935     {
6936       /* Never relax.  Modify fr_opcode to NULL to verify it's value in
6937          md_apply_fix.  */
6938       fragp->fr_opcode = NULL;
6939       return 0;
6940     }
6941 }
6942
6943
6944 static int
6945 s3_relax_other_inst32 (fragS * fragp)
6946 {
6947   int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6948
6949   if (relaxable_p
6950       && fragp->fr_fix == 4)
6951     {
6952       fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6953       fragp->fr_fix = 2;
6954       return -2;
6955     }
6956   else
6957     return 0;
6958 }
6959
6960 static int
6961 s3_relax_gp_and_pic_inst32 (void)
6962 {
6963   /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
6964      instructions.  We don't change relax size here.  */
6965   return 0;
6966 }
6967
6968 static int
6969 s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
6970 {
6971   int grows = 0;
6972   int adjust_align_p = 0;
6973
6974   /* If the instruction address is odd, make it half word align first.  */
6975   if ((fragp->fr_address) % 2 != 0)
6976     {
6977       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6978         {
6979           fragp->insn_addr = 1;
6980           grows += 1;
6981           adjust_align_p = 1;
6982         }
6983     }
6984
6985   switch (s3_RELAX_TYPE (fragp->fr_subtype))
6986     {
6987     case PC_DISP19div2:
6988       grows += s3_relax_branch_inst32 (fragp);
6989       break;
6990
6991     case PC_DISP8div2:
6992       grows += s3_relax_branch_inst16 (fragp);
6993       break;
6994
6995     case Insn_BCMP :
6996       grows += s3_relax_cmpbranch_inst32 (fragp);
6997       break;
6998
6999     case Insn_GP:
7000     case Insn_PIC:
7001       grows += s3_relax_gp_and_pic_inst32 ();
7002       break;
7003
7004     default:
7005       grows += s3_relax_other_inst32 (fragp);
7006       break;
7007     }
7008
7009   /* newly added */
7010   if (adjust_align_p && fragp->insn_addr)
7011     {
7012       fragp->fr_fix += fragp->insn_addr;
7013     }
7014
7015   return grows;
7016 }
7017
7018 static void
7019 s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7020 {
7021   int r_old;
7022   int r_new;
7023   char backup[20];
7024   fixS *fixp;
7025
7026   r_old = s3_RELAX_OLD (fragp->fr_subtype);
7027   r_new = s3_RELAX_NEW (fragp->fr_subtype);
7028
7029   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
7030   if (fragp->fr_opcode == NULL)
7031     {
7032       memcpy (backup, fragp->fr_literal, r_old);
7033       fragp->fr_fix = r_old;
7034     }
7035   else
7036     {
7037       memcpy (backup, fragp->fr_literal + r_old, r_new);
7038       fragp->fr_fix = r_new;
7039     }
7040
7041   fixp = fragp->tc_frag_data.fixp;
7042   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
7043     {
7044       if (fragp->fr_opcode)
7045         fixp->fx_done = 1;
7046       fixp = fixp->fx_next;
7047     }
7048   while (fixp && fixp->fx_frag == fragp)
7049     {
7050       if (fragp->fr_opcode)
7051         fixp->fx_where -= r_old + fragp->insn_addr;
7052       else
7053         fixp->fx_done = 1;
7054       fixp = fixp->fx_next;
7055     }
7056
7057   if (fragp->insn_addr)
7058     {
7059       s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
7060     }
7061   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
7062   fragp->fr_fix += fragp->insn_addr;
7063 }
7064
7065 static long
7066 s3_pcrel_from (fixS * fixP)
7067 {
7068   long retval = 0;
7069
7070   if (fixP->fx_addsy
7071       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
7072       && (fixP->fx_subsy == NULL))
7073     {
7074       retval = 0;
7075     }
7076   else
7077     {
7078       retval = fixP->fx_where + fixP->fx_frag->fr_address;
7079     }
7080
7081   return retval;
7082 }
7083
7084 static valueT
7085 s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7086 {
7087   int align = bfd_get_section_alignment (stdoutput, segment);
7088   return ((size + (1 << align) - 1) & -(1 << align));
7089 }
7090
7091 static void
7092 s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
7093 {
7094   offsetT value = *valP;
7095   offsetT newval;
7096   offsetT content;
7097   unsigned short HI, LO;
7098
7099   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
7100
7101   gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
7102   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
7103     {
7104       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
7105         fixP->fx_done = 1;
7106     }
7107
7108   /* If this symbol is in a different section then we need to leave it for
7109      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
7110      so we have to undo it's effects here.  */
7111   if (fixP->fx_pcrel)
7112     {
7113       if (fixP->fx_addsy != NULL
7114           && S_IS_DEFINED (fixP->fx_addsy)
7115           && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7116         value += md_pcrel_from (fixP);
7117     }
7118
7119   /* Remember value for emit_reloc.  */
7120   fixP->fx_addnumber = value;
7121
7122   switch (fixP->fx_r_type)
7123     {
7124     case BFD_RELOC_HI16_S:
7125       if (fixP->fx_done)        /* For la rd, imm32.  */
7126         {
7127           newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7128           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
7129           newval |= (HI & 0x3fff) << 1;
7130           newval |= ((HI >> 14) & 0x3) << 16;
7131           s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7132         }
7133       break;
7134     case BFD_RELOC_LO16:
7135       if (fixP->fx_done)        /* For la rd, imm32.  */
7136         {
7137           newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7138           LO = (value) & 0xffff;
7139           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
7140           newval |= ((LO >> 14) & 0x3) << 16;
7141           s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7142         }
7143       break;
7144     case BFD_RELOC_SCORE_JMP:
7145       {
7146         content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7147         value = fixP->fx_offset;
7148         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
7149         s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7150       }
7151       break;
7152
7153     case BFD_RELOC_SCORE_IMM30:
7154       {
7155         content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7156         value = fixP->fx_offset;
7157         value >>= 2;
7158         content = (content & ~0x7f7fff7f80LL)
7159           | (((value & 0xff) >> 0) << 7)
7160           | (((value & 0x7fff00) >> 8) << 16)
7161           | (((value & 0x3f800000) >> 23) << 32);
7162         s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7163         break;
7164       }
7165
7166     case BFD_RELOC_SCORE_IMM32:
7167       {
7168         content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7169         value = fixP->fx_offset;
7170         content = (content & ~0x7f7fff7fe0LL)
7171           | ((value & 0x3ff) << 5)
7172           | (((value >> 10) & 0x7fff) << 16)
7173           | (((value >> 25) & 0x7f) << 32);
7174         s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7175         break;
7176       }
7177
7178     case BFD_RELOC_SCORE_BRANCH:
7179       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7180         value = fixP->fx_offset;
7181       else
7182         fixP->fx_done = 1;
7183
7184       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7185
7186       /* Don't check c-bit.  */
7187       if (fixP->fx_frag->fr_opcode != 0)
7188         {
7189           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7190             {
7191               as_bad_where (fixP->fx_file, fixP->fx_line,
7192                             _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
7193               return;
7194             }
7195           content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7196           content &= 0xfe00;
7197           content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7198           s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7199           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
7200           fixP->fx_size = 2;
7201         }
7202       else
7203         {
7204           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7205             {
7206               as_bad_where (fixP->fx_file, fixP->fx_line,
7207                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7208               return;
7209             }
7210           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7211           content &= 0xfc00fc01;
7212           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7213           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7214         }
7215       break;
7216     case BFD_RELOC_SCORE16_JMP:
7217       content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7218       content &= 0xf001;
7219       value = fixP->fx_offset & 0xfff;
7220       content = (content & 0xfc01) | (value & 0xffe);
7221       s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7222       break;
7223     case BFD_RELOC_SCORE16_BRANCH:
7224       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7225       /* Don't check c-bit.  */
7226       if (fixP->fx_frag->fr_opcode != 0)
7227         {
7228           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7229               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7230             value = fixP->fx_offset;
7231           else
7232             fixP->fx_done = 1;
7233           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7234             {
7235               as_bad_where (fixP->fx_file, fixP->fx_line,
7236                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7237               return;
7238             }
7239           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7240           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7241           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7242           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7243           fixP->fx_size = 4;
7244           break;
7245         }
7246       else
7247         {
7248           /* In different section.  */
7249           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7250               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7251             value = fixP->fx_offset;
7252           else
7253             fixP->fx_done = 1;
7254
7255           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7256             {
7257               as_bad_where (fixP->fx_file, fixP->fx_line,
7258                             _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
7259               return;
7260             }
7261
7262           content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7263           content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7264           s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7265           break;
7266         }
7267
7268       break;
7269
7270     case BFD_RELOC_SCORE_BCMP:
7271       if (fixP->fx_frag->fr_opcode != 0)
7272         {
7273           char *buf_ptr = buf;
7274           buf_ptr += 2;
7275
7276           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7277             value = fixP->fx_offset;
7278           else
7279             fixP->fx_done = 1;
7280
7281           /* NOTE!!!
7282              bcmp -> cmp! and branch, so value -= 2.  */
7283           value -= 2;
7284
7285           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7286             {
7287               as_bad_where (fixP->fx_file, fixP->fx_line,
7288                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
7289               return;
7290             }
7291
7292           content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
7293           content &= 0xfc00fc01;
7294           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7295           s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
7296           /* change relocation type to BFD_RELOC_SCORE_BRANCH */
7297           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7298           fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
7299           break;
7300         }
7301       else
7302         {
7303           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7304             value = fixP->fx_offset;
7305           else
7306             fixP->fx_done = 1;
7307
7308           content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7309
7310           if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7311             {
7312               as_bad_where (fixP->fx_file, fixP->fx_line,
7313                             _(" branch relocation truncate (0x%x)  [-2^9 ~ 2^9-1]"), (unsigned int) value);
7314               return;
7315             }
7316
7317           value >>= 1;
7318           content &= ~0x03e00381;
7319           content = content
7320             | (value & 0x1)
7321             | (((value & 0xe) >> 1) << 7)
7322             | (((value & 0x1f0) >> 4) << 21);
7323
7324           s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7325           break;
7326         }
7327
7328     case BFD_RELOC_8:
7329       if (fixP->fx_done || fixP->fx_pcrel)
7330         s3_md_number_to_chars (buf, value, 1);
7331 #ifdef OBJ_ELF
7332       else
7333         {
7334           value = fixP->fx_offset;
7335           s3_md_number_to_chars (buf, value, 1);
7336         }
7337 #endif
7338       break;
7339
7340     case BFD_RELOC_16:
7341       if (fixP->fx_done || fixP->fx_pcrel)
7342         s3_md_number_to_chars (buf, value, 2);
7343 #ifdef OBJ_ELF
7344       else
7345         {
7346           value = fixP->fx_offset;
7347           s3_md_number_to_chars (buf, value, 2);
7348         }
7349 #endif
7350       break;
7351     case BFD_RELOC_RVA:
7352     case BFD_RELOC_32:
7353       if (fixP->fx_done || fixP->fx_pcrel)
7354         md_number_to_chars (buf, value, 4);
7355 #ifdef OBJ_ELF
7356       else
7357         {
7358           value = fixP->fx_offset;
7359           md_number_to_chars (buf, value, 4);
7360         }
7361 #endif
7362       break;
7363     case BFD_RELOC_VTABLE_INHERIT:
7364       fixP->fx_done = 0;
7365       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
7366         S_SET_WEAK (fixP->fx_addsy);
7367       break;
7368     case BFD_RELOC_VTABLE_ENTRY:
7369       fixP->fx_done = 0;
7370       break;
7371     case BFD_RELOC_SCORE_GPREL15:
7372       content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7373       /* c-bit.  */
7374       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
7375         fixP->fx_r_type = BFD_RELOC_NONE;
7376       fixP->fx_done = 0;
7377       break;
7378     case BFD_RELOC_SCORE_GOT15:
7379     case BFD_RELOC_SCORE_DUMMY_HI16:
7380     case BFD_RELOC_SCORE_GOT_LO16:
7381     case BFD_RELOC_SCORE_CALL15:
7382     case BFD_RELOC_GPREL32:
7383       break;
7384     case BFD_RELOC_NONE:
7385     default:
7386       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
7387     }
7388 }
7389
7390 static arelent **
7391 s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7392 {
7393   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
7394   arelent *reloc;
7395   bfd_reloc_code_real_type code;
7396   const char *type;
7397
7398   reloc = retval[0] = XNEW (arelent);
7399   retval[1] = NULL;
7400
7401   reloc->sym_ptr_ptr = XNEW (asymbol *);
7402   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7403   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7404   reloc->addend = fixp->fx_offset;
7405
7406   /* If this is a variant frag, we may need to adjust the existing
7407      reloc and generate a new one.  */
7408   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
7409     {
7410       /* Update instruction imm bit.  */
7411       offsetT newval;
7412       unsigned short off;
7413       char *buf;
7414
7415       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
7416       newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7417       off = fixp->fx_offset >> 16;
7418       newval |= (off & 0x3fff) << 1;
7419       newval |= ((off >> 14) & 0x3) << 16;
7420       s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7421
7422       buf += s3_INSN_SIZE;
7423       newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7424       off = fixp->fx_offset & 0xffff;
7425       newval |= ((off & 0x3fff) << 1);
7426       newval |= (((off >> 14) & 0x3) << 16);
7427       s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7428
7429       retval[1] = XNEW (arelent);
7430       retval[2] = NULL;
7431       retval[1]->sym_ptr_ptr = XNEW (asymbol *);
7432       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7433       retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
7434
7435       retval[1]->addend = 0;
7436       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
7437       gas_assert (retval[1]->howto != NULL);
7438
7439       fixp->fx_r_type = BFD_RELOC_HI16_S;
7440     }
7441
7442   code = fixp->fx_r_type;
7443   switch (fixp->fx_r_type)
7444     {
7445     case BFD_RELOC_32:
7446       if (fixp->fx_pcrel)
7447         {
7448           code = BFD_RELOC_32_PCREL;
7449           break;
7450         }
7451       /* Fall through.  */
7452     case BFD_RELOC_HI16_S:
7453     case BFD_RELOC_LO16:
7454     case BFD_RELOC_SCORE_JMP:
7455     case BFD_RELOC_SCORE_BRANCH:
7456     case BFD_RELOC_SCORE16_JMP:
7457     case BFD_RELOC_SCORE16_BRANCH:
7458     case BFD_RELOC_SCORE_BCMP:
7459     case BFD_RELOC_VTABLE_ENTRY:
7460     case BFD_RELOC_VTABLE_INHERIT:
7461     case BFD_RELOC_SCORE_GPREL15:
7462     case BFD_RELOC_SCORE_GOT15:
7463     case BFD_RELOC_SCORE_DUMMY_HI16:
7464     case BFD_RELOC_SCORE_GOT_LO16:
7465     case BFD_RELOC_SCORE_CALL15:
7466     case BFD_RELOC_GPREL32:
7467     case BFD_RELOC_NONE:
7468     case BFD_RELOC_SCORE_IMM30:
7469     case BFD_RELOC_SCORE_IMM32:
7470       code = fixp->fx_r_type;
7471       break;
7472     default:
7473       type = _("<unknown>");
7474       as_bad_where (fixp->fx_file, fixp->fx_line,
7475                     _("cannot represent %s relocation in this object file format"), type);
7476       return NULL;
7477     }
7478
7479   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7480   if (reloc->howto == NULL)
7481     {
7482       as_bad_where (fixp->fx_file, fixp->fx_line,
7483                     _("cannot represent %s relocation in this object file format1"),
7484                     bfd_get_reloc_code_name (code));
7485       return NULL;
7486     }
7487   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
7488      vtable entry to be used in the relocation's section offset.  */
7489   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
7490     reloc->address = fixp->fx_offset;
7491
7492   return retval;
7493 }
7494
7495 void
7496 md_assemble (char *str)
7497 {
7498   if (score3)
7499     s3_assemble (str);
7500   else
7501     s7_assemble (str);
7502 }
7503
7504 /* We handle all bad expressions here, so that we can report the faulty
7505    instruction in the error message.  */
7506 void
7507 md_operand (expressionS * exp)
7508 {
7509   if (score3)
7510     s3_operand (exp);
7511   else
7512     s7_operand (exp);
7513 }
7514
7515 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7516    for use in the a.out file, and stores them in the array pointed to by buf.
7517    This knows about the endian-ness of the target machine and does
7518    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
7519    2 (short) and 4 (long)  Floating numbers are put out as a series of
7520    LITTLENUMS (shorts, here at least).  */
7521 void
7522 md_number_to_chars (char *buf, valueT val, int n)
7523 {
7524   if (score3)
7525     s3_number_to_chars (buf, val, n);
7526   else
7527     s7_number_to_chars (buf, val, n);
7528 }
7529
7530 /* Turn a string in input_line_pointer into a floating point constant
7531    of type TYPE, and store the appropriate bytes in *LITP.  The number
7532    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
7533    returned, or NULL on OK.
7534
7535    Note that fp constants aren't represent in the normal way on the ARM.
7536    In big endian mode, things are as expected.  However, in little endian
7537    mode fp constants are big-endian word-wise, and little-endian byte-wise
7538    within the words.  For example, (double) 1.1 in big endian mode is
7539    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7540    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
7541 const char *
7542 md_atof (int type, char *litP, int *sizeP)
7543 {
7544   if (score3)
7545     return s3_atof (type, litP, sizeP);
7546   else
7547     return s7_atof (type, litP, sizeP);
7548 }
7549
7550 void
7551 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
7552 {
7553   if (score3)
7554     s3_frag_check (fragp);
7555   else
7556     s7_frag_check (fragp);
7557 }
7558
7559 /* Implementation of TC_VALIDATE_FIX.
7560    Called before md_apply_fix() and after md_convert_frag().  */
7561 void
7562 score_validate_fix (fixS *fixP)
7563 {
7564   if (score3)
7565     s3_validate_fix (fixP);
7566   else
7567     s7_validate_fix (fixP);
7568 }
7569
7570 int
7571 score_force_relocation (struct fix *fixp)
7572 {
7573   if (score3)
7574     return s3_force_relocation (fixp);
7575   else
7576     return s7_force_relocation (fixp);
7577 }
7578
7579 /* Implementation of md_frag_check.
7580    Called after md_convert_frag().  */
7581 bfd_boolean
7582 score_fix_adjustable (fixS * fixP)
7583 {
7584   if (score3)
7585     return s3_fix_adjustable (fixP);
7586   else
7587     return s7_fix_adjustable (fixP);
7588 }
7589
7590 void
7591 score_elf_final_processing (void)
7592 {
7593   if (score3)
7594     s3_elf_final_processing ();
7595   else
7596     s7_elf_final_processing ();
7597 }
7598
7599 /* In this function, we determine whether s3_GP instruction should do relaxation,
7600    for the label being against was known now.
7601    Doing this here but not in md_relax_frag() can induce iteration times
7602    in stage of doing relax.  */
7603 int
7604 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
7605 {
7606   if (score3)
7607     return s3_estimate_size_before_relax (fragp, sec);
7608   else
7609     return s7_estimate_size_before_relax (fragp, sec);
7610 }
7611
7612 int
7613 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
7614 {
7615   if (score3)
7616     return s3_relax_frag (sec, fragp, stretch);
7617   else
7618     return s7_relax_frag (sec, fragp, stretch);
7619 }
7620
7621 void
7622 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7623 {
7624   if (score3)
7625     return s3_convert_frag (abfd, sec, fragp);
7626   else
7627     return s7_convert_frag (abfd, sec, fragp);
7628 }
7629
7630 long
7631 md_pcrel_from (fixS * fixP)
7632 {
7633   if (score3)
7634     return s3_pcrel_from (fixP);
7635   else
7636     return s7_pcrel_from (fixP);
7637 }
7638
7639 /* Round up a section size to the appropriate boundary.  */
7640 valueT
7641 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7642 {
7643   if (score3)
7644     return s3_section_align (segment, size);
7645   else
7646     return s7_section_align (segment, size);
7647 }
7648
7649 void
7650 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
7651 {
7652   if (score3)
7653     return s3_apply_fix (fixP, valP, seg);
7654   else
7655     return s7_apply_fix (fixP, valP, seg);
7656 }
7657
7658 /* Translate internal representation of relocation info to BFD target format.  */
7659 arelent **
7660 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7661 {
7662   if (score3)
7663     return s3_gen_reloc (section, fixp);
7664   else
7665     return s7_gen_reloc (section, fixp);
7666 }
7667
7668 void
7669 md_begin (void)
7670 {
7671   s3_begin ();
7672   s7_begin ();
7673 }
7674
7675 static void
7676 score_set_mach (const char *arg)
7677 {
7678   if (strcmp (arg, MARCH_SCORE3) == 0)
7679     {
7680       score3 = 1;
7681       score7 = 0;
7682       s3_score3d = 1;
7683     }
7684   else if (strcmp (arg, MARCH_SCORE7) == 0)
7685     {
7686       score3 = 0;
7687       score7 = 1;
7688       s7_score7d = 1;
7689       s7_university_version = 0;
7690       s7_vector_size = s7_SCORE7_PIPELINE;
7691     }
7692   else if (strcmp (arg, MARCH_SCORE5) == 0)
7693     {
7694       score3 = 0;
7695       score7 = 1;
7696       s7_score7d = 1;
7697       s7_university_version = 0;
7698       s7_vector_size = s7_SCORE5_PIPELINE;
7699     }
7700   else if (strcmp (arg, MARCH_SCORE5U) == 0)
7701     {
7702       score3 = 0;
7703       score7 = 1;
7704       s7_score7d = 1;
7705       s7_university_version = 1;
7706       s7_vector_size = s7_SCORE5_PIPELINE;
7707     }
7708   else
7709     {
7710       as_bad (_("unknown architecture `%s'\n"), arg);
7711     }
7712 }
7713
7714 int
7715 md_parse_option (int c, const char *arg)
7716 {
7717   switch (c)
7718     {
7719 #ifdef OPTION_EB
7720     case OPTION_EB:
7721       target_big_endian = 1;
7722       break;
7723 #endif
7724 #ifdef OPTION_EL
7725     case OPTION_EL:
7726       target_big_endian = 0;
7727       break;
7728 #endif
7729     case OPTION_FIXDD:
7730       s3_fix_data_dependency = 1;
7731       s7_fix_data_dependency = 1;
7732       break;
7733     case OPTION_NWARN:
7734       s3_warn_fix_data_dependency = 0;
7735       s7_warn_fix_data_dependency = 0;
7736       break;
7737     case OPTION_SCORE5:
7738       score3 = 0;
7739       score7 = 1;
7740       s7_university_version = 0;
7741       s7_vector_size = s7_SCORE5_PIPELINE;
7742       break;
7743     case OPTION_SCORE5U:
7744       score3 = 0;
7745       score7 = 1;
7746       s7_university_version = 1;
7747       s7_vector_size = s7_SCORE5_PIPELINE;
7748       break;
7749     case OPTION_SCORE7:
7750       score3 = 0;
7751       score7 = 1;
7752       s7_score7d = 1;
7753       s7_university_version = 0;
7754       s7_vector_size = s7_SCORE7_PIPELINE;
7755       break;
7756     case OPTION_SCORE3:
7757       score3 = 1;
7758       score7 = 0;
7759       s3_score3d = 1;
7760       break;
7761     case OPTION_R1:
7762       s3_nor1 = 0;
7763       s7_nor1 = 0;
7764       break;
7765     case 'G':
7766       s3_g_switch_value = atoi (arg);
7767       s7_g_switch_value = atoi (arg);
7768       break;
7769     case OPTION_O0:
7770       s3_g_opt = 0;
7771       s7_g_opt = 0;
7772       break;
7773     case OPTION_SCORE_VERSION:
7774       printf (_("Sunplus-v2-0-0-20060510\n"));
7775       break;
7776     case OPTION_PIC:
7777       s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now.  */
7778       s7_score_pic = s7_PIC;
7779       s3_g_switch_value = 0;    /* Must set -G num as 0 to generate s3_PIC code.  */
7780       s7_g_switch_value = 0;    /* Must set -G num as 0 to generate s7_PIC code.  */
7781       break;
7782     case OPTION_MARCH:
7783       score_set_mach (arg);
7784       break;
7785     default:
7786       return 0;
7787     }
7788   return 1;
7789 }
7790
7791 void
7792 md_show_usage (FILE * fp)
7793 {
7794   fprintf (fp, _(" Score-specific assembler options:\n"));
7795 #ifdef OPTION_EB
7796   fprintf (fp, _("\
7797         -EB\t\tassemble code for a big-endian cpu\n"));
7798 #endif
7799
7800 #ifdef OPTION_EL
7801   fprintf (fp, _("\
7802         -EL\t\tassemble code for a little-endian cpu\n"));
7803 #endif
7804
7805   fprintf (fp, _("\
7806         -FIXDD\t\tfix data dependencies\n"));
7807   fprintf (fp, _("\
7808         -NWARN\t\tdo not print warning message when fixing data dependencies\n"));
7809   fprintf (fp, _("\
7810         -SCORE5\t\tassemble code for target SCORE5\n"));
7811   fprintf (fp, _("\
7812         -SCORE5U\tassemble code for target SCORE5U\n"));
7813   fprintf (fp, _("\
7814         -SCORE7\t\tassemble code for target SCORE7 [default]\n"));
7815   fprintf (fp, _("\
7816         -SCORE3\t\tassemble code for target SCORE3\n"));
7817   fprintf (fp, _("\
7818         -march=score7\tassemble code for target SCORE7 [default]\n"));
7819   fprintf (fp, _("\
7820         -march=score3\tassemble code for target SCORE3\n"));
7821   fprintf (fp, _("\
7822         -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
7823   fprintf (fp, _("\
7824         -KPIC\t\tgenerate PIC\n"));
7825   fprintf (fp, _("\
7826         -O0\t\tdo not perform any optimizations\n"));
7827   fprintf (fp, _("\
7828         -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n"));
7829   fprintf (fp, _("\
7830         -V \t\tSunplus release version\n"));
7831 }