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