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