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