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