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