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