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