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