]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-score.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-score.c
CommitLineData
1c0d3aa6 1/* tc-score.c -- Assembler for Score
a2c58332 2 Copyright (C) 2006-2022 Free Software Foundation, Inc.
1c0d3aa6 3 Contributed by:
c3b7224a 4 Brain.lin (brain.lin@sunplusct.com)
1c0d3aa6
NC
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
ec2655a6 12 the Free Software Foundation; either version 3, or (at your option)
1c0d3aa6
NC
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
c3b7224a
NC
25#include "tc-score7.c"
26
27static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED);
28static void s3_s_score_text (int ignore);
29static void s3_score_s_section (int ignore);
30static void s3_s_change_sec (int sec);
31static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED);
32static void s3_s_score_ent (int aent);
33static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED);
34static void s3_s_score_end (int x ATTRIBUTE_UNUSED);
35static void s3_s_score_set (int x ATTRIBUTE_UNUSED);
36static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED);
37static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
38static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED);
39static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
40static void s3_s_score_lcomm (int bytes_p);
41
42static void s_score_bss (int ignore ATTRIBUTE_UNUSED);
43static void s_score_text (int ignore);
44static void s_section (int ignore);
45static void s_change_sec (int sec);
46static void s_score_mask (int reg_type ATTRIBUTE_UNUSED);
47static void s_score_ent (int aent);
48static void s_score_frame (int ignore ATTRIBUTE_UNUSED);
49static void s_score_end (int x ATTRIBUTE_UNUSED);
50static void s_score_set (int x ATTRIBUTE_UNUSED);
51static void s_score_cpload (int ignore ATTRIBUTE_UNUSED);
52static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
53static void s_score_gpword (int ignore ATTRIBUTE_UNUSED);
54static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
55static void s_score_lcomm (int bytes_p);
56
57/* s3: hooks. */
58static void s3_md_number_to_chars (char *buf, valueT val, int n);
59static valueT s3_md_chars_to_number (char *buf, int n);
60static void s3_assemble (char *str);
91d6fa6a 61static void s3_operand (expressionS *);
c3b7224a
NC
62static void s3_begin (void);
63static void s3_number_to_chars (char *buf, valueT val, int n);
6d4af3c2 64static const char *s3_atof (int type, char *litP, int *sizeP);
c3b7224a
NC
65static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED);
66static void s3_validate_fix (fixS *fixP);
67static int s3_force_relocation (struct fix *fixp);
5b7c81bd 68static bool s3_fix_adjustable (fixS * fixP);
c3b7224a
NC
69static void s3_elf_final_processing (void);
70static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED);
71static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED);
72static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp);
73static long s3_pcrel_from (fixS * fixP);
74static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size);
75static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg);
76static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp);
77
78/* s3: utils. */
79static void s3_do_ldst_insn (char *);
80static void s3_do_crdcrscrsimm5 (char *);
81static void s3_do_ldst_unalign (char *);
82static void s3_do_ldst_atomic (char *);
83static void s3_do_ldst_cop (char *);
84static void s3_do_macro_li_rdi32 (char *);
85static void s3_do_macro_la_rdi32 (char *);
86static void s3_do_macro_rdi32hi (char *);
87static void s3_do_macro_rdi32lo (char *);
88static void s3_do_macro_mul_rdrsrs (char *);
89static void s3_do_macro_bcmp (char *);
90static void s3_do_macro_bcmpz (char *);
91static void s3_do_macro_ldst_label (char *);
92static void s3_do_branch (char *);
93static void s3_do_jump (char *);
94static void s3_do_empty (char *);
95static void s3_do16_int (char *);
96static void s3_do_rdrsrs (char *);
97static void s3_do_rdsi16 (char *);
98static void s3_do_rdrssi14 (char *);
99static void s3_do_sub_rdsi16 (char *);
100static void s3_do_sub_rdi16 (char *);
101static void s3_do_sub_rdrssi14 (char *);
102static void s3_do_rdrsi5 (char *);
103static void s3_do_rdrsi14 (char *);
104static void s3_do_rdi16 (char *);
105static void s3_do_ldis (char *);
106static void s3_do_xrsi5 (char *);
107static void s3_do_rdrs (char *);
108static void s3_do_rdxrs (char *);
109static void s3_do_rsrs (char *);
110static void s3_do_rdcrs (char *);
111static void s3_do_rdsrs (char *);
112static void s3_do_rd (char *);
113static void s3_do16_dsp (char *);
114static void s3_do16_dsp2 (char *);
115static void s3_do_dsp (char *);
116static void s3_do_dsp2 (char *);
117static void s3_do_dsp3 (char *);
118static void s3_do_rs (char *);
119static void s3_do_i15 (char *);
120static void s3_do_xi5x (char *);
121static void s3_do_ceinst (char *);
122static void s3_do_cache (char *);
123static void s3_do16_rdrs2 (char *);
124static void s3_do16_br (char *);
125static void s3_do16_brr (char *);
126static void s3_do_ltb (char *);
127static void s3_do16_mv_cmp (char *);
128static void s3_do16_addi (char *);
129static void s3_do16_cmpi (char *);
130static void s3_do16_rdi5 (char *);
131static void s3_do16_xi5 (char *);
132static void s3_do16_ldst_insn (char *);
f9e53abc
NC
133static void s3_do16_slli_srli (char *);
134static void s3_do16_ldiu (char *);
c3b7224a
NC
135static void s3_do16_push_pop (char *);
136static void s3_do16_rpush (char *);
137static void s3_do16_rpop (char *);
138static void s3_do16_branch (char *);
139static void s3_do_lw48 (char *);
140static void s3_do_sw48 (char *);
141static void s3_do_ldi48 (char *);
142static void s3_do_sdbbp48 (char *);
143static void s3_do_and48 (char *);
144static void s3_do_or48 (char *);
145static void s3_do_mbitclr (char *);
146static void s3_do_mbitset (char *);
147static void s3_do_rdi16_pic (char *);
148static void s3_do_addi_s_pic (char *);
149static void s3_do_addi_u_pic (char *);
150static void s3_do_lw_pic (char *);
151
152#define MARCH_SCORE3 "score3"
153#define MARCH_SCORE3D "score3d"
154#define MARCH_SCORE7 "score7"
155#define MARCH_SCORE7D "score7d"
156#define MARCH_SCORE5 "score5"
157#define MARCH_SCORE5U "score5u"
158
159#define SCORE_BI_ENDIAN
160
161#ifdef SCORE_BI_ENDIAN
162#define OPTION_EB (OPTION_MD_BASE + 0)
163#define OPTION_EL (OPTION_MD_BASE + 1)
164#else
165#if TARGET_BYTES_BIG_ENDIAN
166#define OPTION_EB (OPTION_MD_BASE + 0)
167#else
168#define OPTION_EL (OPTION_MD_BASE + 1)
169#endif
170#endif
171#define OPTION_FIXDD (OPTION_MD_BASE + 2)
172#define OPTION_NWARN (OPTION_MD_BASE + 3)
173#define OPTION_SCORE5 (OPTION_MD_BASE + 4)
174#define OPTION_SCORE5U (OPTION_MD_BASE + 5)
175#define OPTION_SCORE7 (OPTION_MD_BASE + 6)
176#define OPTION_R1 (OPTION_MD_BASE + 7)
177#define OPTION_O0 (OPTION_MD_BASE + 8)
178#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
179#define OPTION_PIC (OPTION_MD_BASE + 10)
180#define OPTION_MARCH (OPTION_MD_BASE + 11)
181#define OPTION_SCORE3 (OPTION_MD_BASE + 12)
182
183/* This array holds the chars that always start a comment. If the
184 pre-processor is disabled, these aren't very useful. */
185const char comment_chars[] = "#";
186const char line_comment_chars[] = "#";
187const char line_separator_chars[] = ";";
188/* Chars that can be used to separate mant from exp in floating point numbers. */
189const char EXP_CHARS[] = "eE";
190const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
1c0d3aa6
NC
191
192#ifdef OBJ_ELF
c3b7224a
NC
193/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
194symbolS *GOT_symbol;
195#endif
196
197const pseudo_typeS md_pseudo_table[] =
198{
199 {"bss", s_score_bss, 0},
200 {"text", s_score_text, 0},
201 {"word", cons, 4},
202 {"long", cons, 4},
203 {"extend", float_cons, 'x'},
204 {"ldouble", float_cons, 'x'},
205 {"packed", float_cons, 'p'},
206 {"end", s_score_end, 0},
207 {"ent", s_score_ent, 0},
208 {"frame", s_score_frame, 0},
209 {"rdata", s_change_sec, 'r'},
210 {"sdata", s_change_sec, 's'},
211 {"set", s_score_set, 0},
212 {"mask", s_score_mask, 'R'},
213 {"dword", cons, 8},
214 {"lcomm", s_score_lcomm, 1},
215 {"section", s_section, 0},
216 {"cpload", s_score_cpload, 0},
217 {"cprestore", s_score_cprestore, 0},
218 {"gpword", s_score_gpword, 0},
219 {"cpadd", s_score_cpadd, 0},
220 {0, 0, 0}
221};
222
223const char *md_shortopts = "nO::g::G:";
224struct option md_longopts[] =
225{
226#ifdef OPTION_EB
227 {"EB" , no_argument, NULL, OPTION_EB},
228#endif
229#ifdef OPTION_EL
230 {"EL" , no_argument, NULL, OPTION_EL},
1c0d3aa6 231#endif
c3b7224a
NC
232 {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
233 {"NWARN" , no_argument, NULL, OPTION_NWARN},
234 {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
235 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
236 {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
237 {"USE_R1" , no_argument, NULL, OPTION_R1},
238 {"O0" , no_argument, NULL, OPTION_O0},
239 {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
240 {"KPIC" , no_argument, NULL, OPTION_PIC},
241 {"march=" , required_argument, NULL, OPTION_MARCH},
242 {"SCORE3" , no_argument, NULL, OPTION_SCORE3},
243 {NULL , no_argument, NULL, 0}
244};
245
246size_t md_longopts_size = sizeof (md_longopts);
1c0d3aa6 247
c3b7224a
NC
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
1c0d3aa6
NC
257
258/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
c3b7224a
NC
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)
1c0d3aa6
NC
267
268/* The name of the readonly data section. */
c3b7224a 269#define s3_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
1c0d3aa6
NC
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
c3b7224a 279#define s3_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
1c0d3aa6
NC
280 ((relax_substateT) \
281 (((old) << 23) \
282 | ((new) << 16) \
283 | ((type) << 9) \
284 | ((reloc1) << 5) \
285 | ((reloc2) << 1) \
286 | ((opt) ? 1 : 0)))
287
c3b7224a
NC
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)
1c0d3aa6 294
c3b7224a
NC
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)
1c0d3aa6 302
c3b7224a 303#define s3_INSN_NAME_LEN 16
1c0d3aa6 304
c3b7224a
NC
305/* Relax will need some padding for alignment. */
306#define s3_RELAX_PAD_BYTE 3
1c0d3aa6 307
1c0d3aa6 308
c3b7224a 309#define s3_USE_GLOBAL_POINTER_OPT 1
1c0d3aa6 310
c3b7224a
NC
311/* Enumeration matching entries in table above. */
312enum 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
321enum s3_score_pic_level
322{
323 s3_NO_PIC,
324 s3_PIC
325};
326static enum s3_score_pic_level s3_score_pic = s3_NO_PIC;
48903831 327
c3b7224a
NC
328enum s3_insn_type_for_dependency
329{
330 s3_D_mtcr,
331 s3_D_all_insn
332};
1c0d3aa6 333
c3b7224a
NC
334struct s3_insn_to_dependency
335{
b9bb4a93 336 const char *insn_name;
c3b7224a
NC
337 enum s3_insn_type_for_dependency type;
338};
1c0d3aa6 339
c3b7224a
NC
340struct 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
351static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] =
352{
33eaf5de 353 /* move special instruction. */
c3b7224a
NC
354 {"mtcr", s3_D_mtcr},
355};
356
357static const struct s3_data_dependency s3_data_dependency_table[] =
358{
33eaf5de 359 /* Status register. */
c3b7224a
NC
360 {s3_D_mtcr, "cr0", s3_D_all_insn, "", 5, 1, 0},
361};
362
363/* Used to contain constructed error messages. */
364static char s3_err_msg[255];
365
366static int s3_fix_data_dependency = 0;
367static int s3_warn_fix_data_dependency = 1;
368
369static int s3_in_my_get_expression = 0;
1c0d3aa6
NC
370
371/* Default, pop warning message when using r1. */
c3b7224a 372static int s3_nor1 = 1;
1c0d3aa6 373
c3b7224a
NC
374/* Default will do instruction relax, -O0 will set s3_g_opt = 0. */
375static unsigned int s3_g_opt = 1;
1c0d3aa6
NC
376
377/* The size of the small data section. */
c3b7224a 378static unsigned int s3_g_switch_value = 8;
1c0d3aa6 379
c3b7224a 380static segT s3_pdr_seg;
1c0d3aa6 381
c3b7224a 382struct s3_score_it
1c0d3aa6 383{
c3b7224a
NC
384 char name[s3_INSN_NAME_LEN];
385 bfd_vma instruction;
386 bfd_vma relax_inst;
1c0d3aa6
NC
387 int size;
388 int relax_size;
389 enum score_insn_type type;
c3b7224a 390 char str[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6
NC
391 const char *error;
392 int bwarn;
c3b7224a 393 char reg[s3_INSN_NAME_LEN];
1c0d3aa6
NC
394 struct
395 {
396 bfd_reloc_code_real_type type;
397 expressionS exp;
398 int pc_rel;
399 }reloc;
400};
c3b7224a 401static struct s3_score_it s3_inst;
1c0d3aa6 402
c3b7224a 403typedef struct s3_proc
1c0d3aa6
NC
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;
c3b7224a
NC
413} s3_procS;
414static s3_procS s3_cur_proc;
415static s3_procS *s3_cur_proc_ptr;
416static int s3_numprocs;
1c0d3aa6 417
1c0d3aa6 418
1c0d3aa6 419/* Structure for a hash table entry for a register. */
c3b7224a 420struct s3_reg_entry
1c0d3aa6
NC
421{
422 const char *name;
423 int number;
424};
425
c3b7224a 426static const struct s3_reg_entry s3_score_rn_table[] =
1c0d3aa6
NC
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
c3b7224a 439static const struct s3_reg_entry s3_score_srn_table[] =
1c0d3aa6
NC
440{
441 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
442 {NULL, 0}
443};
444
c3b7224a 445static const struct s3_reg_entry s3_score_crn_table[] =
1c0d3aa6
NC
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
c3b7224a 458struct s3_reg_map
1c0d3aa6 459{
c3b7224a 460 const struct s3_reg_entry *names;
1c0d3aa6 461 int max_regno;
629310ab 462 htab_t htab;
1c0d3aa6
NC
463 const char *expected;
464};
465
c3b7224a 466static struct s3_reg_map s3_all_reg_maps[] =
1c0d3aa6 467{
c3b7224a
NC
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")},
1c0d3aa6
NC
471};
472
629310ab
ML
473static htab_t s3_score_ops_hsh = NULL;
474static htab_t s3_dependency_insn_hsh = NULL;
1c0d3aa6 475
1c0d3aa6 476
c3b7224a
NC
477struct s3_datafield_range
478{
479 int data_type;
480 int bits;
481 int range[2];
482};
483
484static 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 ) */
f9e53abc
NC
533 {_IMM32, 32, {0, 0xfffffff}},
534 {_SIMM32, 32, {-0x80000000, 0x7fffffff}},
535 {_IMM11, 11, {0, (1 << 11) - 1}},
c3b7224a
NC
536};
537
538struct s3_asm_opcode
1c0d3aa6 539{
c3b7224a 540 /* Instruction name. */
d3ce72d0 541 const char *template_name;
c3b7224a
NC
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 *);
1c0d3aa6
NC
557};
558
f9e53abc 559static const struct s3_asm_opcode s3_score_ldst_insns[] =
c3b7224a
NC
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},
1c0d3aa6
NC
585};
586
f9e53abc 587static const struct s3_asm_opcode s3_score_insns[] =
c3b7224a
NC
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},
f9e53abc 693 {"breql", 0x00001009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
c3b7224a
NC
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},
f9e53abc
NC
751
752 /* ldi <-> ldiu!. */
c3b7224a
NC
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
1c0d3aa6 952 /* Macro instruction. */
c3b7224a
NC
953 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_li_rdi32},
954
1c0d3aa6 955 /* la reg, imm32 -->(1) ldi reg, simm16
f9e53abc
NC
956 (2) ldis reg, %HI(imm32)
957 ori reg, %LO(imm32)
958
1c0d3aa6
NC
959 la reg, symbol -->(1) lis reg, %HI(imm32)
960 ori reg, %LO(imm32) */
c3b7224a
NC
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
1c0d3aa6 985 /* Assembler use internal. */
c3b7224a
NC
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},
1c0d3aa6
NC
1002};
1003
c3b7224a 1004#define s3_SCORE3_PIPELINE 3
1c0d3aa6 1005
c3b7224a
NC
1006static int s3_university_version = 0;
1007static int s3_vector_size = s3_SCORE3_PIPELINE;
1008static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE];
1c0d3aa6 1009
c3b7224a 1010static int s3_score3d = 1;
b0253a53 1011
1c0d3aa6 1012static int
c3b7224a 1013s3_end_of_line (char *str)
1c0d3aa6 1014{
c3b7224a 1015 int retval = s3_SUCCESS;
1c0d3aa6 1016
c3b7224a 1017 s3_skip_whitespace (str);
1c0d3aa6
NC
1018 if (*str != '\0')
1019 {
c3b7224a 1020 retval = (int) s3_FAIL;
1c0d3aa6 1021
c3b7224a
NC
1022 if (!s3_inst.error)
1023 s3_inst.error = s3_BAD_GARBAGE;
1c0d3aa6
NC
1024 }
1025
1026 return retval;
1027}
1028
1029static int
629310ab 1030s3_score_reg_parse (char **ccp, htab_t htab)
1c0d3aa6
NC
1031{
1032 char *start = *ccp;
1033 char c;
1034 char *p;
c3b7224a 1035 struct s3_reg_entry *reg;
1c0d3aa6
NC
1036
1037 p = start;
1038 if (!ISALPHA (*p) || !is_name_beginner (*p))
c3b7224a 1039 return (int) s3_FAIL;
1c0d3aa6
NC
1040
1041 c = *p++;
1042
1043 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1044 c = *p++;
1045
1046 *--p = 0;
629310ab 1047 reg = (struct s3_reg_entry *) str_hash_find (htab, start);
1c0d3aa6
NC
1048 *p = c;
1049
1050 if (reg)
1051 {
1052 *ccp = p;
1053 return reg->number;
1054 }
c3b7224a 1055 return (int) s3_FAIL;
1c0d3aa6
NC
1056}
1057
1058/* If shift <= 0, only return reg. */
1059
1060static int
c3b7224a 1061s3_reg_required_here (char **str, int shift, enum s3_score_reg_type reg_type)
1c0d3aa6 1062{
c3b7224a
NC
1063 static char buff[s3_MAX_LITERAL_POOL_SIZE];
1064 int reg = (int) s3_FAIL;
1c0d3aa6
NC
1065 char *start = *str;
1066
c3b7224a 1067 if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[reg_type].htab)) != (int) s3_FAIL)
1c0d3aa6 1068 {
c3b7224a 1069 if (reg_type == s3_REG_TYPE_SCORE)
1c0d3aa6 1070 {
c3b7224a 1071 if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
1c0d3aa6 1072 {
33eaf5de 1073 as_warn (_("Using temp register (r1)"));
c3b7224a 1074 s3_inst.bwarn = 1;
1c0d3aa6
NC
1075 }
1076 }
1077 if (shift >= 0)
1078 {
c3b7224a
NC
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);
1c0d3aa6 1083 else
c3b7224a 1084 strcpy (s3_inst.reg, "");
1c0d3aa6 1085
c3b7224a 1086 s3_inst.instruction |= (bfd_vma) reg << shift;
1c0d3aa6
NC
1087 }
1088 }
1089 else
1090 {
1091 *str = start;
1092 sprintf (buff, _("register expected, not '%.100s'"), start);
c3b7224a 1093 s3_inst.error = buff;
1c0d3aa6
NC
1094 }
1095
1096 return reg;
1097}
1098
1099static int
c3b7224a 1100s3_skip_past_comma (char **str)
1c0d3aa6
NC
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 {
c3b7224a
NC
1111 s3_inst.error = s3_BAD_SKIP_COMMA;
1112 return (int) s3_FAIL;
1c0d3aa6
NC
1113 }
1114 }
1115
1116 if ((c == '\0') || (comma == 0))
1117 {
c3b7224a
NC
1118 s3_inst.error = s3_BAD_SKIP_COMMA;
1119 return (int) s3_FAIL;
1c0d3aa6
NC
1120 }
1121
1122 *str = p;
c3b7224a 1123 return comma ? s3_SUCCESS : (int) s3_FAIL;
1c0d3aa6
NC
1124}
1125
1126static void
c3b7224a 1127s3_do_rdrsrs (char *str)
1c0d3aa6 1128{
c3b7224a
NC
1129 int reg;
1130 s3_skip_whitespace (str);
1c0d3aa6 1131
c3b7224a
NC
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)
1c0d3aa6
NC
1138 {
1139 return;
1140 }
1141 else
1142 {
c3b7224a
NC
1143 /* Check mulr, mulur rd is even number. */
1144 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
f9e53abc 1145 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
c3b7224a
NC
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)))
1c0d3aa6 1157 {
c3b7224a
NC
1158 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
1159 | (((s3_inst.instruction >> 15) & 0xf) << 4);
1160 s3_inst.relax_size = 2;
1c0d3aa6
NC
1161 }
1162 else
1163 {
c3b7224a 1164 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1165 }
1166 }
1167}
1168
1169static int
c3b7224a 1170s3_walk_no_bignums (symbolS * sp)
1c0d3aa6
NC
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)
c3b7224a 1176 return (s3_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1c0d3aa6 1177 || (symbol_get_value_expression (sp)->X_op_symbol
f9e53abc 1178 && s3_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1c0d3aa6
NC
1179
1180 return 0;
1181}
1182
1183static int
c3b7224a 1184s3_my_get_expression (expressionS * ep, char **str)
1c0d3aa6
NC
1185{
1186 char *save_in;
1c0d3aa6
NC
1187
1188 save_in = input_line_pointer;
1189 input_line_pointer = *str;
c3b7224a 1190 s3_in_my_get_expression = 1;
f9e53abc 1191 (void) expression (ep);
c3b7224a 1192 s3_in_my_get_expression = 0;
1c0d3aa6
NC
1193
1194 if (ep->X_op == O_illegal)
1195 {
1196 *str = input_line_pointer;
1197 input_line_pointer = save_in;
c3b7224a
NC
1198 s3_inst.error = _("illegal expression");
1199 return (int) s3_FAIL;
1c0d3aa6
NC
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
c3b7224a
NC
1206 && (s3_walk_no_bignums (ep->X_add_symbol)
1207 || (ep->X_op_symbol && s3_walk_no_bignums (ep->X_op_symbol)))))
1c0d3aa6 1208 {
c3b7224a 1209 s3_inst.error = _("invalid constant");
1c0d3aa6
NC
1210 *str = input_line_pointer;
1211 input_line_pointer = save_in;
c3b7224a 1212 return (int) s3_FAIL;
1c0d3aa6
NC
1213 }
1214
b138abaa 1215 if ((ep->X_add_symbol != NULL)
c3b7224a
NC
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;
b138abaa
NC
1229 *str = input_line_pointer;
1230 input_line_pointer = save_in;
c3b7224a 1231 return (int) s3_FAIL;
b138abaa
NC
1232 }
1233
1c0d3aa6
NC
1234 *str = input_line_pointer;
1235 input_line_pointer = save_in;
c3b7224a 1236 return s3_SUCCESS;
1c0d3aa6
NC
1237}
1238
1239/* Check if an immediate is valid. If so, convert it to the right format. */
c3b7224a
NC
1240static bfd_signed_vma
1241s3_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
1c0d3aa6
NC
1242{
1243 switch (data_type)
1244 {
1245 case _VALUE_HI16:
1246 {
c3b7224a 1247 bfd_signed_vma val_hi = ((val & 0xffff0000) >> 16);
1c0d3aa6 1248
c3b7224a
NC
1249 if (s3_score_df_range[data_type].range[0] <= val_hi
1250 && val_hi <= s3_score_df_range[data_type].range[1])
1c0d3aa6
NC
1251 return val_hi;
1252 }
1253 break;
1254
1255 case _VALUE_LO16:
1256 {
c3b7224a 1257 bfd_signed_vma val_lo = (val & 0xffff);
1c0d3aa6 1258
c3b7224a
NC
1259 if (s3_score_df_range[data_type].range[0] <= val_lo
1260 && val_lo <= s3_score_df_range[data_type].range[1])
1c0d3aa6
NC
1261 return val_lo;
1262 }
1263 break;
1264
b0253a53
ML
1265 case _SIMM14:
1266 if (hex_p == 1)
1267 {
1268 if (!(val >= -0x2000 && val <= 0x3fff))
1269 {
c3b7224a 1270 return (int) s3_FAIL;
b0253a53
ML
1271 }
1272 }
1273 else
1274 {
1275 if (!(val >= -8192 && val <= 8191))
1276 {
c3b7224a 1277 return (int) s3_FAIL;
b0253a53
ML
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 {
c3b7224a 1289 return (int) s3_FAIL;
b0253a53
ML
1290 }
1291 }
1292 else
1293 {
1294 if (!(val >= -32767 && val <= 32768))
1295 {
c3b7224a 1296 return (int) s3_FAIL;
b0253a53
ML
1297 }
1298 }
1299
1300 val = -val;
1301 return val;
1302 break;
1303
c3b7224a
NC
1304 case _IMM5_MULTI_LOAD:
1305 if (val >= 2 && val <= 32)
f9e53abc 1306 {
c3b7224a 1307 if (val == 32)
f9e53abc 1308 val = 0;
c3b7224a 1309 return val;
f9e53abc
NC
1310 }
1311 return (int) s3_FAIL;
c3b7224a
NC
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
1c0d3aa6 1323 default:
b0253a53 1324 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1c0d3aa6
NC
1325 val = -val;
1326
c3b7224a
NC
1327 if (s3_score_df_range[data_type].range[0] <= val
1328 && val <= s3_score_df_range[data_type].range[1])
1c0d3aa6
NC
1329 return val;
1330
1331 break;
1332 }
1333
c3b7224a 1334 return (int) s3_FAIL;
1c0d3aa6
NC
1335}
1336
1337static int
c3b7224a 1338s3_data_op2 (char **str, int shift, enum score_data_type data_type)
1c0d3aa6 1339{
c3b7224a
NC
1340 bfd_signed_vma value;
1341 char data_exp[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6
NC
1342 char *dataptr;
1343 int cnt = 0;
1344 char *pp = NULL;
1345
c3b7224a
NC
1346 s3_skip_whitespace (*str);
1347 s3_inst.error = NULL;
1c0d3aa6
NC
1348 dataptr = * str;
1349
b0253a53
ML
1350 /* Set hex_p to zero. */
1351 int hex_p = 0;
1352
c3b7224a 1353 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s3_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1c0d3aa6
NC
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 {
c3b7224a
NC
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 */
1c0d3aa6
NC
1370 *str = dataptr;
1371 }
1372 else /* process 16 bit */
1373 {
c3b7224a 1374 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
1c0d3aa6 1375 {
c3b7224a 1376 return (int) s3_FAIL;
1c0d3aa6
NC
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
f9e53abc 1388 if ((dataptr != NULL)
b0253a53
ML
1389 && (((strstr (dataptr, "0x")) != NULL)
1390 || ((strstr (dataptr, "0X")) != NULL)))
f9e53abc 1391 {
b0253a53
ML
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)
c3b7224a
NC
1401 && (data_type != _IMM5_MULTI_LOAD)
1402 && (data_type != _IMM11)
b0253a53
ML
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)
c3b7224a
NC
1410 && (data_type != _GP_IMM15)
1411 && (data_type != _SIMM5)
1412 && (data_type != _SIMM6)
1413 && (data_type != _IMM32)
1414 && (data_type != _SIMM32))
b0253a53
ML
1415 {
1416 data_type += 24;
1417 }
1c0d3aa6 1418 }
b138abaa 1419
c3b7224a
NC
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)
b138abaa 1425 && (((*dataptr >= 'a') && (*dataptr <= 'z'))
f9e53abc
NC
1426 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1427 || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1428 || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
b138abaa 1429 {
c3b7224a
NC
1430 s3_inst.error = s3_BAD_ARGS;
1431 return (int) s3_FAIL;
b138abaa 1432 }
1c0d3aa6
NC
1433 }
1434
c3b7224a 1435 if ((s3_inst.reloc.exp.X_add_symbol)
1c0d3aa6
NC
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)
c3b7224a
NC
1442 || (data_type == _IMM5_MULTI_LOAD)
1443 || (data_type == _IMM11)
1c0d3aa6
NC
1444 || (data_type == _IMM14)
1445 || (data_type == _IMM20)
1446 || (data_type == _IMM16)
1447 || (data_type == _IMM15)
1448 || (data_type == _IMM4)))
1449 {
c3b7224a
NC
1450 s3_inst.error = s3_BAD_ARGS;
1451 return (int) s3_FAIL;
1c0d3aa6
NC
1452 }
1453
c3b7224a 1454 if (s3_inst.reloc.exp.X_add_symbol)
1c0d3aa6
NC
1455 {
1456 switch (data_type)
1457 {
1458 case _SIMM16_LA:
c3b7224a 1459 return (int) s3_FAIL;
1c0d3aa6 1460 case _VALUE_HI16:
c3b7224a
NC
1461 s3_inst.reloc.type = BFD_RELOC_HI16_S;
1462 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1463 break;
1464 case _VALUE_LO16:
c3b7224a
NC
1465 s3_inst.reloc.type = BFD_RELOC_LO16;
1466 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1467 break;
1468 case _GP_IMM15:
c3b7224a
NC
1469 s3_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1470 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1471 break;
1472 case _SIMM16_pic:
1473 case _IMM16_LO16_pic:
c3b7224a
NC
1474 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1475 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1476 break;
1477 default:
c3b7224a
NC
1478 s3_inst.reloc.type = BFD_RELOC_32;
1479 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1480 break;
1481 }
1482 }
1483 else
1484 {
1485 if (data_type == _IMM16_pic)
1486 {
c3b7224a
NC
1487 s3_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1488 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
1489 }
1490
c3b7224a 1491 if (data_type == _SIMM16_LA && s3_inst.reloc.exp.X_unsigned == 1)
1c0d3aa6 1492 {
c3b7224a
NC
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)
1c0d3aa6 1496 {
c3b7224a
NC
1497 s3_inst.instruction |= 0x8000000;
1498 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1499 return s3_SUCCESS;
1c0d3aa6
NC
1500 }
1501 }
1502 else
1503 {
c3b7224a 1504 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, hex_p);
1c0d3aa6
NC
1505 }
1506
c3b7224a 1507 if (value == (int) s3_FAIL)
1c0d3aa6 1508 {
c3b7224a
NC
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))
1c0d3aa6 1523 {
c3b7224a 1524 sprintf (s3_err_msg,
14119072 1525 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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]);
1c0d3aa6
NC
1528 }
1529 else
1530 {
c3b7224a 1531 sprintf (s3_err_msg,
14119072 1532 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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]);
1c0d3aa6
NC
1535 }
1536
c3b7224a
NC
1537 s3_inst.error = s3_err_msg;
1538 return (int) s3_FAIL;
1c0d3aa6
NC
1539 }
1540
c3b7224a
NC
1541 if (((s3_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1542 && data_type != _IMM5_MULTI_LOAD)
1c0d3aa6 1543 {
c3b7224a 1544 value &= (1 << s3_score_df_range[data_type].bits) - 1;
1c0d3aa6
NC
1545 }
1546
c3b7224a
NC
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))
1c0d3aa6 1556 {
c3b7224a
NC
1557 s3_inst.error = _("invalid constant: bit expression not defined");
1558 return (int) s3_FAIL;
1c0d3aa6
NC
1559 }
1560 }
1561
c3b7224a 1562 return s3_SUCCESS;
1c0d3aa6
NC
1563}
1564
1565/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1c0d3aa6 1566static void
c3b7224a 1567s3_do_rdsi16 (char *str)
1c0d3aa6 1568{
c3b7224a 1569 s3_skip_whitespace (str);
1c0d3aa6 1570
c3b7224a
NC
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)
1c0d3aa6
NC
1575 return;
1576
c3b7224a
NC
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)*/
f9e53abc
NC
1595 if (((s3_inst.instruction & 0x1ffe0) == 0)
1596 || (((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)
1597 && (s3_inst.instruction & 0x003e) != 0))
c3b7224a
NC
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 */
f9e53abc 1610 else if (((s3_inst.instruction & 0x2000000) == 0x02000000) && (s3_inst.relax_inst!=0x8000))
1c0d3aa6 1611 {
c3b7224a 1612 /* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/
f9e53abc
NC
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)))
1c0d3aa6 1617 {
c3b7224a
NC
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;
1c0d3aa6
NC
1621 }
1622 else
1623 {
c3b7224a 1624 s3_inst.relax_inst =0x8000;
1c0d3aa6
NC
1625 }
1626 }
c3b7224a
NC
1627
1628 else if (((s3_inst.instruction >> 20) & 0x10) == 0x10)
1c0d3aa6 1629 {
c3b7224a 1630 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1631 }
1632}
1633
c3b7224a
NC
1634static void
1635s3_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
1c0d3aa6 1646/* Handle subi/subi.c. */
c3b7224a
NC
1647static void
1648s3_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}
1c0d3aa6 1657
c3b7224a 1658/* Handle subis/subis.c. */
1c0d3aa6 1659static void
c3b7224a 1660s3_do_sub_rdi16 (char *str)
1c0d3aa6 1661{
c3b7224a 1662 s3_skip_whitespace (str);
1c0d3aa6 1663
c3b7224a
NC
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);
1c0d3aa6
NC
1668}
1669
1c0d3aa6 1670/* Handle addri/addri.c. */
1c0d3aa6 1671static void
c3b7224a 1672s3_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1c0d3aa6 1673{
c3b7224a 1674 s3_skip_whitespace (str);
1c0d3aa6 1675
c3b7224a
NC
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);
1c0d3aa6
NC
1681}
1682
1683/* Handle subri.c/subri. */
1684static void
c3b7224a 1685s3_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1c0d3aa6 1686{
c3b7224a 1687 s3_skip_whitespace (str);
1c0d3aa6 1688
c3b7224a
NC
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);
1c0d3aa6
NC
1695}
1696
c3b7224a
NC
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) */
1c0d3aa6 1699static void
f9e53abc 1700s3_do_rdrsi5 (char *str)
1c0d3aa6 1701{
c3b7224a 1702 s3_skip_whitespace (str);
1c0d3aa6 1703
c3b7224a
NC
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)
1c0d3aa6
NC
1710 return;
1711
c3b7224a
NC
1712 if ((((s3_inst.instruction >> 20) & 0x1f) == ((s3_inst.instruction >> 15) & 0x1f))
1713 && (s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
1c0d3aa6 1714 {
c3b7224a
NC
1715 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f) ) | (((s3_inst.instruction >> 15) & 0xf) << 5);
1716 s3_inst.relax_size = 2;
1c0d3aa6
NC
1717 }
1718 else
c3b7224a 1719 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1720}
1721
c3b7224a
NC
1722/* Handle andri/orri/andri.c/orri.c.
1723 0 ~ ((2^14)-1) */
1c0d3aa6 1724static void
c3b7224a 1725s3_do_rdrsi14 (char *str)
1c0d3aa6 1726{
c3b7224a 1727 s3_skip_whitespace (str);
1c0d3aa6 1728
c3b7224a
NC
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);
1c0d3aa6
NC
1735}
1736
1737/* Handle bittst.c. */
1738static void
c3b7224a 1739s3_do_xrsi5 (char *str)
1c0d3aa6 1740{
c3b7224a 1741 s3_skip_whitespace (str);
1c0d3aa6 1742
c3b7224a
NC
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)
1c0d3aa6
NC
1747 return;
1748
c3b7224a 1749 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
1c0d3aa6 1750 {
c3b7224a
NC
1751 s3_inst.relax_inst |= ((s3_inst.instruction >> 10) & 0x1f) | (((s3_inst.instruction >> 15) & 0xf) << 5);
1752 s3_inst.relax_size = 2;
1c0d3aa6
NC
1753 }
1754 else
c3b7224a 1755 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1756}
1757
14119072 1758/* Handle addis/andi/ori/andis/oris/ldis. */
1c0d3aa6 1759static void
c3b7224a 1760s3_do_rdi16 (char *str)
1c0d3aa6 1761{
c3b7224a 1762 s3_skip_whitespace (str);
1c0d3aa6 1763
c3b7224a
NC
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)
1c0d3aa6 1768 return;
c3b7224a
NC
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 {
f9e53abc 1794 s3_inst.relax_inst =0x5c00; /* addi! */
c3b7224a
NC
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 }
1c0d3aa6
NC
1805}
1806
1807static void
c3b7224a 1808s3_do_macro_rdi32hi (char *str)
1c0d3aa6 1809{
c3b7224a 1810 s3_skip_whitespace (str);
1c0d3aa6 1811
c3b7224a
NC
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);
1c0d3aa6
NC
1816}
1817
1818static void
c3b7224a 1819s3_do_macro_rdi32lo (char *str)
1c0d3aa6 1820{
c3b7224a 1821 s3_skip_whitespace (str);
1c0d3aa6 1822
c3b7224a
NC
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);
1c0d3aa6
NC
1827}
1828
1829/* Handle ldis_pic. */
1c0d3aa6 1830static void
c3b7224a 1831s3_do_rdi16_pic (char *str)
1c0d3aa6 1832{
c3b7224a 1833 s3_skip_whitespace (str);
1c0d3aa6 1834
c3b7224a
NC
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);
1c0d3aa6
NC
1839}
1840
1841/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1c0d3aa6 1842static void
c3b7224a 1843s3_do_addi_s_pic (char *str)
1c0d3aa6 1844{
c3b7224a 1845 s3_skip_whitespace (str);
1c0d3aa6 1846
c3b7224a
NC
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);
1c0d3aa6
NC
1851}
1852
1853/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1c0d3aa6 1854static void
c3b7224a 1855s3_do_addi_u_pic (char *str)
1c0d3aa6 1856{
c3b7224a 1857 s3_skip_whitespace (str);
1c0d3aa6 1858
c3b7224a
NC
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);
1c0d3aa6
NC
1863}
1864
1865/* Handle mfceh/mfcel/mtceh/mtchl. */
1c0d3aa6 1866static void
c3b7224a 1867s3_do_rd (char *str)
1c0d3aa6 1868{
c3b7224a 1869 s3_skip_whitespace (str);
1c0d3aa6 1870
c3b7224a
NC
1871 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL)
1872 s3_end_of_line (str);
1c0d3aa6
NC
1873}
1874
c3b7224a 1875/* Handle br{cond},cmpzteq.c ,cmpztmi.c ,cmpz.c */
1c0d3aa6 1876static void
c3b7224a 1877s3_do_rs (char *str)
1c0d3aa6 1878{
c3b7224a 1879 s3_skip_whitespace (str);
1c0d3aa6 1880
c3b7224a
NC
1881 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
1882 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
1883 return;
1884
c3b7224a 1885 if ((s3_inst.relax_inst != 0x8000) )
1c0d3aa6 1886 {
c3b7224a
NC
1887 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) &0x1f);
1888 s3_inst.relax_size = 2;
1c0d3aa6
NC
1889 }
1890 else
c3b7224a 1891 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1892}
1893
1894static void
c3b7224a 1895s3_do_i15 (char *str)
1c0d3aa6 1896{
c3b7224a 1897 s3_skip_whitespace (str);
1c0d3aa6 1898
c3b7224a
NC
1899 if (s3_data_op2 (&str, 10, _IMM15) != (int) s3_FAIL)
1900 s3_end_of_line (str);
1c0d3aa6
NC
1901}
1902
1903static void
c3b7224a 1904s3_do_xi5x (char *str)
1c0d3aa6 1905{
c3b7224a 1906 s3_skip_whitespace (str);
1c0d3aa6 1907
c3b7224a 1908 if (s3_data_op2 (&str, 15, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
1909 return;
1910
c3b7224a 1911 if (s3_inst.relax_inst != 0x8000)
1c0d3aa6 1912 {
f9e53abc 1913 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f);
c3b7224a 1914 s3_inst.relax_size = 2;
1c0d3aa6
NC
1915 }
1916}
1917
1918static void
c3b7224a 1919s3_do_rdrs (char *str)
1c0d3aa6 1920{
c3b7224a 1921 s3_skip_whitespace (str);
1c0d3aa6 1922
c3b7224a
NC
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)
1c0d3aa6
NC
1927 return;
1928
c3b7224a 1929 if (s3_inst.relax_inst != 0x8000)
1c0d3aa6 1930 {
c3b7224a 1931 if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/
1c0d3aa6 1932 {
c3b7224a
NC
1933 /* mv! rd : 5bit , ra : 5bit */
1934 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5);
f9e53abc 1935 s3_inst.relax_size = 2;
1c0d3aa6 1936 }
c3b7224a 1937 else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 1938 {
c3b7224a
NC
1939 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4)
1940 | (((s3_inst.instruction >> 20) & 0xf) << 8);
1941 s3_inst.relax_size = 2;
1c0d3aa6
NC
1942 }
1943 else
1944 {
c3b7224a 1945 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
1946 }
1947 }
1948}
1949
1950/* Handle mfcr/mtcr. */
1951static void
c3b7224a 1952s3_do_rdcrs (char *str)
1c0d3aa6 1953{
c3b7224a 1954 s3_skip_whitespace (str);
1c0d3aa6 1955
c3b7224a
NC
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);
1c0d3aa6
NC
1960}
1961
1962/* Handle mfsr/mtsr. */
1c0d3aa6 1963static void
c3b7224a 1964s3_do_rdsrs (char *str)
1c0d3aa6 1965{
c3b7224a 1966 s3_skip_whitespace (str);
1c0d3aa6
NC
1967
1968 /* mfsr */
c3b7224a 1969 if ((s3_inst.instruction & 0xff) == 0x50)
1c0d3aa6 1970 {
c3b7224a
NC
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);
1c0d3aa6
NC
1975 }
1976 else
1977 {
c3b7224a
NC
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);
1c0d3aa6
NC
1981 }
1982}
1983
1984/* Handle neg. */
1c0d3aa6 1985static void
c3b7224a 1986s3_do_rdxrs (char *str)
1c0d3aa6 1987{
c3b7224a 1988 s3_skip_whitespace (str);
1c0d3aa6 1989
c3b7224a
NC
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)
1c0d3aa6
NC
1994 return;
1995
c3b7224a
NC
1996 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 10) & 0x10) == 0)
1997 && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 1998 {
c3b7224a
NC
1999 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) << 4) | (((s3_inst.instruction >> 20) & 0xf) << 8);
2000 s3_inst.relax_size = 2;
1c0d3aa6
NC
2001 }
2002 else
c3b7224a 2003 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
2004}
2005
2006/* Handle cmp.c/cmp<cond>. */
2007static void
c3b7224a 2008s3_do_rsrs (char *str)
1c0d3aa6 2009{
c3b7224a 2010 s3_skip_whitespace (str);
1c0d3aa6 2011
c3b7224a
NC
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)
1c0d3aa6
NC
2016 return;
2017
c3b7224a 2018 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
1c0d3aa6 2019 {
c3b7224a
NC
2020 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
2021 s3_inst.relax_size = 2;
1c0d3aa6
NC
2022 }
2023 else
c3b7224a 2024 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
2025}
2026
2027static void
c3b7224a 2028s3_do_ceinst (char *str)
1c0d3aa6
NC
2029{
2030 char *strbak;
2031
2032 strbak = str;
c3b7224a
NC
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)
1c0d3aa6
NC
2045 {
2046 return;
2047 }
2048 else
2049 {
2050 str = strbak;
c3b7224a 2051 if (s3_data_op2 (&str, 0, _IMM25) == (int) s3_FAIL)
1c0d3aa6
NC
2052 return;
2053 }
2054}
2055
2056static int
c3b7224a 2057s3_reglow_required_here (char **str, int shift)
1c0d3aa6 2058{
c3b7224a 2059 static char buff[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6
NC
2060 int reg;
2061 char *start = *str;
2062
c3b7224a 2063 if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[s3_REG_TYPE_SCORE].htab)) != (int) s3_FAIL)
1c0d3aa6 2064 {
c3b7224a 2065 if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
1c0d3aa6 2066 {
14119072 2067 as_warn (_("Using temp register(r1)"));
c3b7224a 2068 s3_inst.bwarn = 1;
1c0d3aa6
NC
2069 }
2070 if (reg < 16)
2071 {
2072 if (shift >= 0)
c3b7224a 2073 s3_inst.instruction |= (bfd_vma) reg << shift;
1c0d3aa6
NC
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;
33eaf5de 2081 sprintf (buff, _("low register (r0-r15) expected, not '%.100s'"), start);
c3b7224a
NC
2082 s3_inst.error = buff;
2083 return (int) s3_FAIL;
1c0d3aa6
NC
2084}
2085
c3b7224a 2086/* Handle add!/and!/or!/sub!. */
1c0d3aa6 2087static void
c3b7224a 2088s3_do16_rdrs2 (char *str)
1c0d3aa6 2089{
c3b7224a 2090 s3_skip_whitespace (str);
1c0d3aa6 2091
c3b7224a
NC
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)
1c0d3aa6
NC
2096 {
2097 return;
2098 }
c3b7224a
NC
2099}
2100
2101/* Handle br!/brl!. */
2102static void
2103s3_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)
1c0d3aa6 2109 {
c3b7224a 2110 return;
1c0d3aa6
NC
2111 }
2112}
2113
c3b7224a 2114/* Handle brr!. */
1c0d3aa6 2115static void
c3b7224a 2116s3_do16_brr (char *str)
1c0d3aa6
NC
2117{
2118 int rd = 0;
2119
c3b7224a 2120 s3_skip_whitespace (str);
1c0d3aa6 2121
c3b7224a
NC
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)
1c0d3aa6
NC
2124 {
2125 return;
2126 }
1c0d3aa6
NC
2127}
2128
c3b7224a 2129/*Handle ltbw / ltbh / ltbb */
1c0d3aa6 2130static void
c3b7224a 2131s3_do_ltb (char *str)
1c0d3aa6 2132{
c3b7224a
NC
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 }
1c0d3aa6 2139
c3b7224a
NC
2140 s3_skip_whitespace (str);
2141 if (*str++ != '[')
1c0d3aa6 2142 {
c3b7224a 2143 s3_inst.error = _("missing [");
1c0d3aa6
NC
2144 return;
2145 }
c3b7224a
NC
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)
1c0d3aa6 2150 {
c3b7224a 2151 return;
1c0d3aa6 2152 }
1c0d3aa6 2153
c3b7224a
NC
2154 s3_skip_whitespace (str);
2155 if (*str++ != ']')
1c0d3aa6 2156 {
c3b7224a
NC
2157 s3_inst.error = _("missing ]");
2158 return;
1c0d3aa6
NC
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. */
2168static fixS *
c3b7224a 2169s3_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1c0d3aa6
NC
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
2188static void
c3b7224a 2189s3_init_dependency_vector (void)
1c0d3aa6
NC
2190{
2191 int i;
2192
c3b7224a
NC
2193 for (i = 0; i < s3_vector_size; i++)
2194 memset (&s3_dependency_vector[i], '\0', sizeof (s3_dependency_vector[i]));
1c0d3aa6
NC
2195
2196 return;
2197}
2198
c3b7224a
NC
2199static enum s3_insn_type_for_dependency
2200s3_dependency_type_from_insn (char *insn_name)
1c0d3aa6 2201{
c3b7224a
NC
2202 char name[s3_INSN_NAME_LEN];
2203 const struct s3_insn_to_dependency *tmp;
1c0d3aa6
NC
2204
2205 strcpy (name, insn_name);
fe0e921f
AM
2206 tmp = (const struct s3_insn_to_dependency *)
2207 str_hash_find (s3_dependency_insn_hsh, name);
1c0d3aa6
NC
2208
2209 if (tmp)
2210 return tmp->type;
2211
c3b7224a 2212 return s3_D_all_insn;
1c0d3aa6
NC
2213}
2214
2215static int
c3b7224a 2216s3_check_dependency (char *pre_insn, char *pre_reg,
f9e53abc 2217 char *cur_insn, char *cur_reg, int *warn_or_error)
1c0d3aa6
NC
2218{
2219 int bubbles = 0;
2220 unsigned int i;
c3b7224a
NC
2221 enum s3_insn_type_for_dependency pre_insn_type;
2222 enum s3_insn_type_for_dependency cur_insn_type;
1c0d3aa6 2223
c3b7224a
NC
2224 pre_insn_type = s3_dependency_type_from_insn (pre_insn);
2225 cur_insn_type = s3_dependency_type_from_insn (cur_insn);
1c0d3aa6 2226
c3b7224a 2227 for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++)
1c0d3aa6 2228 {
c3b7224a
NC
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))
1c0d3aa6 2236 {
c3b7224a
NC
2237 bubbles = s3_data_dependency_table[i].bubblenum_3;
2238 *warn_or_error = s3_data_dependency_table[i].warn_or_error;
1c0d3aa6
NC
2239 break;
2240 }
2241 }
2242
2243 return bubbles;
2244}
2245
2246static void
c3b7224a 2247s3_build_one_frag (struct s3_score_it one_inst)
1c0d3aa6
NC
2248{
2249 char *p;
c3b7224a 2250 int relaxable_p = s3_g_opt;
1c0d3aa6
NC
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);
c3b7224a 2264 s3_md_number_to_chars (p, one_inst.instruction, one_inst.size);
1c0d3aa6
NC
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
c3b7224a
NC
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,
f9e53abc 2275 one_inst.type, 0, 0, relaxable_p),
1c0d3aa6
NC
2276 NULL, 0, NULL);
2277
2278 if (relaxable_p)
c3b7224a 2279 s3_md_number_to_chars (p, one_inst.relax_inst, relax_size);
1c0d3aa6
NC
2280}
2281
2282static void
c3b7224a 2283s3_handle_dependency (struct s3_score_it *theinst)
1c0d3aa6
NC
2284{
2285 int i;
2286 int warn_or_error = 0; /* warn - 0; error - 1 */
2287 int bubbles = 0;
2288 int remainder_bubbles = 0;
c3b7224a
NC
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;
1c0d3aa6
NC
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 {
c3b7224a 2309 s3_init_dependency_vector ();
1c0d3aa6
NC
2310 return;
2311 }
2312
c3b7224a
NC
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]));
1c0d3aa6 2316
c3b7224a 2317 memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i]));
1c0d3aa6
NC
2318
2319 /* There is no dependency between nop and any instruction. */
c3b7224a
NC
2320 if (strcmp (s3_dependency_vector[0].name, "nop") == 0
2321 || strcmp (s3_dependency_vector[0].name, "nop!") == 0)
1c0d3aa6
NC
2322 return;
2323
c3b7224a 2324 strcpy (cur_insn, s3_dependency_vector[0].name);
1c0d3aa6 2325
c3b7224a 2326 for (i = 1; i < s3_vector_size; i++)
1c0d3aa6 2327 {
c3b7224a
NC
2328 /* The element of s3_dependency_vector is NULL. */
2329 if (s3_dependency_vector[i].name[0] == '\0')
1c0d3aa6
NC
2330 continue;
2331
c3b7224a 2332 strcpy (pre_insn, s3_dependency_vector[i].name);
1c0d3aa6 2333
c3b7224a 2334 bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg,
f9e53abc 2335 cur_insn, s3_dependency_vector[0].reg, &warn_or_error);
1c0d3aa6
NC
2336 remainder_bubbles = bubbles - i + 1;
2337
2338 if (remainder_bubbles > 0)
2339 {
2340 int j;
2341
c3b7224a 2342 if (s3_fix_data_dependency == 1)
1c0d3aa6
NC
2343 {
2344 if (remainder_bubbles <= 2)
2345 {
c3b7224a 2346 if (s3_warn_fix_data_dependency)
33eaf5de 2347 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
c3b7224a
NC
2348 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2349 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2350 remainder_bubbles, bubbles);
2351
c3b7224a
NC
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]));
1c0d3aa6
NC
2355
2356 for (j = 1; j <= remainder_bubbles; j++)
2357 {
c3b7224a 2358 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
1c0d3aa6 2359 /* Insert nop!. */
c3b7224a 2360 s3_build_one_frag (nop_inst);
1c0d3aa6
NC
2361 }
2362 }
2363 else
2364 {
c3b7224a 2365 if (s3_warn_fix_data_dependency)
33eaf5de 2366 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
c3b7224a
NC
2367 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2368 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2369 bubbles);
2370
c3b7224a
NC
2371 for (j = 1; j < s3_vector_size; j++)
2372 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
1c0d3aa6
NC
2373
2374 /* Insert pflush. */
c3b7224a 2375 s3_build_one_frag (pflush_inst);
1c0d3aa6
NC
2376 }
2377 }
2378 else
2379 {
2380 if (warn_or_error)
2381 {
33eaf5de 2382 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
f9e53abc
NC
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);
1c0d3aa6
NC
2386 }
2387 else
2388 {
33eaf5de 2389 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
c3b7224a
NC
2390 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2391 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2392 remainder_bubbles, bubbles);
2393 }
2394 }
2395 }
2396 }
2397}
2398
2399static enum insn_class
c3b7224a 2400s3_get_insn_class_from_type (enum score_insn_type type)
1c0d3aa6 2401{
c3b7224a 2402 enum insn_class retval = (int) s3_FAIL;
1c0d3aa6
NC
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:
c3b7224a
NC
2420 case Rd_SI5:
2421 case Rd_SI6:
1c0d3aa6
NC
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:
b138abaa 2461 case Insn_internal:
c3b7224a
NC
2462 case Insn_BCMP:
2463 case Ra_I9_I5:
1c0d3aa6
NC
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;
c3b7224a
NC
2472 case Rd_I30:
2473 case Rd_I32:
2474 retval = INSN_CLASS_48;
2475 break;
1c0d3aa6
NC
2476 default:
2477 abort ();
2478 break;
2479 }
2480 return retval;
2481}
2482
c3b7224a
NC
2483/* Type of p-bits:
2484 48-bit instruction: 1, 1, 0.
2485 32-bit instruction: 1, 0.
2486 16-bit instruction: 0. */
2487static bfd_vma
96d56e9f 2488s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class)
1c0d3aa6 2489{
c3b7224a
NC
2490 bfd_vma result = 0;
2491 bfd_vma m_code_high = 0;
2492 unsigned long m_code_middle = 0;
1c0d3aa6 2493 unsigned long m_code_low = 0;
c3b7224a
NC
2494 bfd_vma pb_high = 0;
2495 unsigned long pb_middle = 0;
1c0d3aa6
NC
2496 unsigned long pb_low = 0;
2497
96d56e9f 2498 if (i_class == INSN_CLASS_48)
c3b7224a
NC
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) |
f9e53abc
NC
2507 pb_middle | (m_code_middle << 1) |
2508 pb_low | m_code_low;
c3b7224a 2509 }
96d56e9f 2510 else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN)
1c0d3aa6
NC
2511 {
2512 pb_high = 0x80000000;
c3b7224a
NC
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;
1c0d3aa6 2517 }
96d56e9f 2518 else if (i_class == INSN_CLASS_16)
1c0d3aa6
NC
2519 {
2520 pb_high = 0;
2521 pb_low = 0;
c3b7224a
NC
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;
1c0d3aa6 2525 }
96d56e9f 2526 else if (i_class == INSN_CLASS_PCE)
1c0d3aa6 2527 {
c3b7224a 2528 /* Keep original. */
1c0d3aa6
NC
2529 pb_high = 0;
2530 pb_low = 0x00008000;
c3b7224a
NC
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;
1c0d3aa6
NC
2534 }
2535 else
2536 {
2537 abort ();
2538 }
2539
1c0d3aa6 2540 return result;
1c0d3aa6
NC
2541}
2542
2543static void
c3b7224a 2544s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2)
1c0d3aa6
NC
2545{
2546 char *p;
5b7c81bd 2547 bool pce_p = false;
c3b7224a 2548 int relaxable_p = s3_g_opt;
1c0d3aa6 2549 int relax_size = 0;
c3b7224a
NC
2550 struct s3_score_it *inst1 = part_1;
2551 struct s3_score_it *inst2 = part_2;
2552 struct s3_score_it backup_inst1;
1c0d3aa6 2553
63b4cc53 2554 pce_p = inst2 != NULL;
c3b7224a 2555 memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it));
1c0d3aa6
NC
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)
f9e53abc 2561 | (inst2->instruction & 0x7FFF);
c3b7224a 2562 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
1c0d3aa6 2563 backup_inst1.relax_inst = 0x8000;
c3b7224a 2564 backup_inst1.size = s3_INSN_SIZE;
1c0d3aa6
NC
2565 backup_inst1.relax_size = 0;
2566 backup_inst1.type = Insn_Type_PCE;
2567 }
2568 else
2569 {
c3b7224a 2570 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction,
f9e53abc 2571 s3_GET_INSN_CLASS (backup_inst1.type));
1c0d3aa6
NC
2572 }
2573
2574 if (backup_inst1.relax_size != 0)
2575 {
2576 enum insn_class tmp;
2577
c3b7224a
NC
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);
1c0d3aa6
NC
2580 }
2581
2582 /* Check data dependency. */
c3b7224a 2583 s3_handle_dependency (&backup_inst1);
1c0d3aa6
NC
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
33eaf5de 2598 actually will call frag_wane.
1c0d3aa6
NC
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);
c3b7224a 2604 s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
1c0d3aa6
NC
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)
c3b7224a 2614 s3_fix_new_score (frag_now, p - frag_now->fr_literal,
f9e53abc
NC
2615 inst1->size, &inst1->reloc.exp,
2616 inst1->reloc.pc_rel, inst1->reloc.type);
1c0d3aa6
NC
2617
2618 if (inst2->reloc.type != BFD_RELOC_NONE)
c3b7224a 2619 s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
f9e53abc 2620 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
1c0d3aa6
NC
2621 }
2622 else
2623 {
2624 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
c3b7224a 2625 s3_fix_new_score (frag_now, p - frag_now->fr_literal,
f9e53abc
NC
2626 backup_inst1.size, &backup_inst1.reloc.exp,
2627 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
1c0d3aa6
NC
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
c3b7224a
NC
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,
f9e53abc 2636 backup_inst1.type, 0, 0, relaxable_p),
1c0d3aa6
NC
2637 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2638
2639 if (relaxable_p)
c3b7224a 2640 s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
1c0d3aa6 2641
c3b7224a 2642 memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it));
1c0d3aa6
NC
2643}
2644
2645static void
5b7c81bd 2646s3_parse_16_32_inst (char *insnstr, bool gen_frag_p)
1c0d3aa6
NC
2647{
2648 char c;
2649 char *p;
2650 char *operator = insnstr;
c3b7224a 2651 const struct s3_asm_opcode *opcode;
1c0d3aa6
NC
2652
2653 /* Parse operator and operands. */
c3b7224a 2654 s3_skip_whitespace (operator);
1c0d3aa6
NC
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
fe0e921f
AM
2666 opcode = (const struct s3_asm_opcode *) str_hash_find (s3_score_ops_hsh,
2667 operator);
c3b7224a
NC
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;
d3ce72d0 2680 sprintf (s3_inst.name, "%s", opcode->template_name);
c3b7224a
NC
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
2695static void
5b7c81bd 2696s3_parse_48_inst (char *insnstr, bool gen_frag_p)
c3b7224a
NC
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
fe0e921f
AM
2713 opcode = (const struct s3_asm_opcode *) str_hash_find (s3_score_ops_hsh,
2714 operator);
1c0d3aa6
NC
2715 *p = c;
2716
c3b7224a
NC
2717 memset (&s3_inst, '\0', sizeof (s3_inst));
2718 sprintf (s3_inst.str, "%s", insnstr);
1c0d3aa6
NC
2719 if (opcode)
2720 {
c3b7224a
NC
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;
d3ce72d0 2727 sprintf (s3_inst.name, "%s", opcode->template_name);
c3b7224a
NC
2728 strcpy (s3_inst.reg, "");
2729 s3_inst.error = NULL;
2730 s3_inst.reloc.type = BFD_RELOC_NONE;
1c0d3aa6
NC
2731
2732 (*opcode->parms) (p);
2733
c3b7224a
NC
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);
1c0d3aa6
NC
2737 }
2738 else
c3b7224a 2739 s3_inst.error = _("unrecognized opcode");
1c0d3aa6
NC
2740}
2741
2742static int
5b7c81bd 2743s3_append_insn (char *str, bool gen_frag_p)
1c0d3aa6 2744{
c3b7224a 2745 int retval = s3_SUCCESS;
1c0d3aa6 2746
c3b7224a 2747 s3_parse_16_32_inst (str, gen_frag_p);
1c0d3aa6 2748
c3b7224a 2749 if (s3_inst.error)
1c0d3aa6 2750 {
c3b7224a
NC
2751 retval = (int) s3_FAIL;
2752 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
2753 s3_inst.error = NULL;
1c0d3aa6
NC
2754 }
2755
2756 return retval;
2757}
2758
1c0d3aa6 2759static void
c3b7224a 2760s3_do16_mv_cmp (char *str)
1c0d3aa6 2761{
c3b7224a 2762 s3_skip_whitespace (str);
1c0d3aa6 2763
c3b7224a
NC
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)
1c0d3aa6
NC
2768 {
2769 return;
2770 }
c3b7224a 2771}
1c0d3aa6 2772
c3b7224a
NC
2773static void
2774s3_do16_cmpi (char *str)
2775{
2776 s3_skip_whitespace (str);
1c0d3aa6 2777
c3b7224a
NC
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;
1c0d3aa6
NC
2784 }
2785}
2786
2787static void
c3b7224a 2788s3_do16_addi (char *str)
1c0d3aa6 2789{
c3b7224a 2790 s3_skip_whitespace (str);
1c0d3aa6 2791
c3b7224a
NC
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)
1c0d3aa6
NC
2796 {
2797 return;
2798 }
1c0d3aa6
NC
2799}
2800
c3b7224a 2801/* Handle bitclr! / bitset! / bittst! / bittgl! */
1c0d3aa6 2802static void
c3b7224a 2803s3_do16_rdi5 (char *str)
1c0d3aa6 2804{
c3b7224a 2805 s3_skip_whitespace (str);
1c0d3aa6 2806
c3b7224a
NC
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)
1c0d3aa6
NC
2811 return;
2812 else
2813 {
c3b7224a
NC
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;
1c0d3aa6
NC
2817 }
2818}
2819
c3b7224a
NC
2820
2821/* Handle sdbbp!. */
1c0d3aa6 2822static void
c3b7224a 2823s3_do16_xi5 (char *str)
1c0d3aa6 2824{
c3b7224a 2825 s3_skip_whitespace (str);
1c0d3aa6 2826
c3b7224a 2827 if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 2828 return;
1c0d3aa6
NC
2829}
2830
2831/* Check that an immediate is word alignment or half word alignment.
2832 If so, convert it to the right format. */
2833static int
c3b7224a 2834s3_validate_immediate_align (int val, unsigned int data_type)
1c0d3aa6
NC
2835{
2836 if (data_type == _IMM5_RSHIFT_1)
2837 {
2838 if (val % 2)
2839 {
c3b7224a
NC
2840 s3_inst.error = _("address offset must be half word alignment");
2841 return (int) s3_FAIL;
1c0d3aa6
NC
2842 }
2843 }
2844 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2845 {
2846 if (val % 4)
2847 {
c3b7224a
NC
2848 s3_inst.error = _("address offset must be word alignment");
2849 return (int) s3_FAIL;
1c0d3aa6
NC
2850 }
2851 }
2852
c3b7224a 2853 return s3_SUCCESS;
1c0d3aa6
NC
2854}
2855
2856static int
c3b7224a 2857s3_exp_ldst_offset (char **str, int shift, unsigned int data_type)
1c0d3aa6
NC
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
c3b7224a
NC
2881 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
2882 return (int) s3_FAIL;
1c0d3aa6 2883
c3b7224a 2884 if (s3_inst.reloc.exp.X_op == O_constant)
1c0d3aa6
NC
2885 {
2886 /* Need to check the immediate align. */
c3b7224a 2887 int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type);
1c0d3aa6 2888
c3b7224a
NC
2889 if (value == (int) s3_FAIL)
2890 return (int) s3_FAIL;
1c0d3aa6 2891
c3b7224a
NC
2892 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
2893 if (value == (int) s3_FAIL)
1c0d3aa6 2894 {
1c0d3aa6 2895 if (data_type < 30)
c3b7224a 2896 sprintf (s3_err_msg,
14119072 2897 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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]);
1c0d3aa6 2900 else
c3b7224a 2901 sprintf (s3_err_msg,
14119072 2902 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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;
1c0d3aa6
NC
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
c3b7224a 2918 if (s3_score_df_range[data_type].range[0] != 0)
1c0d3aa6 2919 {
c3b7224a 2920 value &= (1 << s3_score_df_range[data_type].bits) - 1;
1c0d3aa6
NC
2921 }
2922
c3b7224a 2923 s3_inst.instruction |= value << shift;
1c0d3aa6
NC
2924 }
2925 else
2926 {
c3b7224a 2927 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
2928 }
2929
c3b7224a 2930 return s3_SUCCESS;
1c0d3aa6
NC
2931}
2932
2933static void
c3b7224a 2934s3_do_ldst_insn (char *str)
1c0d3aa6
NC
2935{
2936 int pre_inc = 0;
2937 int conflict_reg;
2938 int value;
2939 char * temp;
1c0d3aa6
NC
2940 char *dataptr;
2941 int reg;
2942 int ldst_idx = 0;
2943
c3b7224a 2944 s3_skip_whitespace (str);
1c0d3aa6 2945
c3b7224a
NC
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))
1c0d3aa6
NC
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++;
c3b7224a 2954 s3_skip_whitespace (str);
1c0d3aa6 2955
c3b7224a 2956 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
2957 return;
2958
2959 /* Conflicts can occur on stores as well as loads. */
2960 conflict_reg = (conflict_reg == reg);
c3b7224a 2961 s3_skip_whitespace (str);
1c0d3aa6
NC
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. */
c3b7224a 2972 if (s3_skip_past_comma (&str) == s3_SUCCESS)
1c0d3aa6 2973 {
c3b7224a
NC
2974 if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL)
2975 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
2976 return;
2977
2978 if (conflict_reg)
2979 {
c3b7224a 2980 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
1c0d3aa6
NC
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 {
c3b7224a 2988 s3_inst.error = _("register same as write-back base");
1c0d3aa6
NC
2989 return;
2990 }
2991 }
2992
c3b7224a
NC
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;
1c0d3aa6
NC
2996
2997 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
c3b7224a 2998 if ((s3_inst.instruction & 0x3e000007) == 0x0e000000)
1c0d3aa6 2999 {
c3b7224a
NC
3000 /* rs = r0, offset = 4 */
3001 if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3002 && (((s3_inst.instruction >> 3) & 0xfff) == 4))
1c0d3aa6 3003 {
c3b7224a
NC
3004 /* Relax to pop!. */
3005 s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f);
3006 s3_inst.relax_size = 2;
1c0d3aa6
NC
3007 }
3008 }
3009 return;
3010 }
3011 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3012 else
3013 {
c3b7224a
NC
3014 s3_SET_INSN_ERROR (NULL);
3015 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3016 {
3017 return;
3018 }
3019
3020 pre_inc = 1;
c3b7224a
NC
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;
1c0d3aa6
NC
3028 return;
3029 }
3030 }
3031 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3032 else
3033 {
c3b7224a 3034 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3035 return;
3036
c3b7224a
NC
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;
1c0d3aa6
NC
3040
3041 /* lbu rd, [rs] -> lbu! rd, [rs] */
3042 if (ldst_idx == INSN_LBU)
3043 {
c3b7224a 3044 s3_inst.relax_inst = INSN16_LBU;
1c0d3aa6
NC
3045 }
3046 else if (ldst_idx == INSN_LH)
3047 {
c3b7224a 3048 s3_inst.relax_inst = INSN16_LH;
1c0d3aa6
NC
3049 }
3050 else if (ldst_idx == INSN_LW)
3051 {
c3b7224a 3052 s3_inst.relax_inst = INSN16_LW;
1c0d3aa6
NC
3053 }
3054 else if (ldst_idx == INSN_SB)
3055 {
c3b7224a 3056 s3_inst.relax_inst = INSN16_SB;
1c0d3aa6
NC
3057 }
3058 else if (ldst_idx == INSN_SH)
3059 {
c3b7224a 3060 s3_inst.relax_inst = INSN16_SH;
1c0d3aa6
NC
3061 }
3062 else if (ldst_idx == INSN_SW)
3063 {
c3b7224a 3064 s3_inst.relax_inst = INSN16_SW;
1c0d3aa6
NC
3065 }
3066 else
3067 {
c3b7224a 3068 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3069 }
3070
3071 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
c3b7224a 3072 /* if ((ldst_idx == INSN_LBU)
f9e53abc
NC
3073 || (ldst_idx == INSN_LH)
3074 || (ldst_idx == INSN_LW)
3075 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/
c3b7224a 3076 if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW))
1c0d3aa6 3077 {
c3b7224a
NC
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))
1c0d3aa6 3080 {
c3b7224a
NC
3081 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) |
3082 (((s3_inst.instruction >> 15) & 0x7) << 5);
3083 s3_inst.relax_size = 2;
1c0d3aa6
NC
3084 }
3085 }
3086
3087 return;
3088 }
3089 }
3090 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3091 else
3092 {
c3b7224a 3093 if (s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6 3094 {
c3b7224a 3095 s3_inst.error = _("pre-indexed expression expected");
1c0d3aa6
NC
3096 return;
3097 }
3098
c3b7224a 3099 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
1c0d3aa6
NC
3100 return;
3101
c3b7224a 3102 s3_skip_whitespace (str);
1c0d3aa6
NC
3103 if (*str++ != ']')
3104 {
c3b7224a 3105 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3106 return;
3107 }
3108
c3b7224a 3109 s3_skip_whitespace (str);
1c0d3aa6
NC
3110 /* ld/sw rD, [rA, simm12]+. */
3111 if (*str == '+')
3112 {
3113 str++;
3114 pre_inc = 1;
3115 if (conflict_reg)
3116 {
c3b7224a 3117 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
1c0d3aa6
NC
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 {
c3b7224a 3125 s3_inst.error = _("register same as write-back base");
1c0d3aa6
NC
3126 return;
3127 }
3128 }
3129 }
3130
c3b7224a 3131 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3132 return;
3133
c3b7224a 3134 if (s3_inst.reloc.exp.X_op == O_constant)
1c0d3aa6 3135 {
1c0d3aa6
NC
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
c3b7224a
NC
3162 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3163 if (value == (int) s3_FAIL)
1c0d3aa6 3164 {
b138abaa 3165 if (data_type < 30)
c3b7224a 3166 sprintf (s3_err_msg,
14119072 3167 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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]);
1c0d3aa6 3170 else
c3b7224a 3171 sprintf (s3_err_msg,
14119072 3172 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
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;
1c0d3aa6
NC
3177 return;
3178 }
3179
c3b7224a
NC
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;
1c0d3aa6 3184 if (pre_inc == 1)
c3b7224a 3185 s3_inst.instruction |= value << 3;
1c0d3aa6 3186 else
c3b7224a 3187 s3_inst.instruction |= value;
1c0d3aa6
NC
3188
3189 /* lw rD, [rA, simm15] */
c3b7224a 3190 if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
1c0d3aa6 3191 {
c3b7224a
NC
3192 /* rD in [r0 - r15]. , ra in [r0-r7] */
3193 if ((((s3_inst.instruction >> 15) & 0x18) == 0)
3194 && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 3195 {
c3b7224a
NC
3196 /* simm = [bit 7], lw -> lw!. */
3197 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
1c0d3aa6 3198 {
c3b7224a
NC
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;
1c0d3aa6
NC
3202 }
3203 else
3204 {
c3b7224a 3205 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3206 }
3207 }
3208 else
3209 {
c3b7224a 3210 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3211 }
3212 }
3213 /* sw rD, [rA, simm15] */
c3b7224a 3214 else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
1c0d3aa6 3215 {
c3b7224a
NC
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))
1c0d3aa6 3218 {
c3b7224a
NC
3219 /* simm15 =7 bit , sw -> sw!. */
3220 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
1c0d3aa6 3221 {
c3b7224a
NC
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;
1c0d3aa6
NC
3225 }
3226 /* rA = r2, sw -> swp!. */
1c0d3aa6
NC
3227 else
3228 {
c3b7224a 3229 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3230 }
3231 }
3232 else
3233 {
c3b7224a 3234 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3235 }
3236 }
3237 /* sw rD, [rA, simm15]+ sw pre. */
c3b7224a 3238 else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
1c0d3aa6 3239 {
c3b7224a
NC
3240 /* simm15 = -4. and ra==r0 */
3241 if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3242 && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
1c0d3aa6 3243 {
1c0d3aa6 3244 /* sw -> push!. */
c3b7224a
NC
3245 s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
3246 s3_inst.relax_size = 2;
1c0d3aa6
NC
3247 }
3248 else
3249 {
c3b7224a 3250 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3251 }
3252 }
3253 else
3254 {
c3b7224a 3255 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3256 }
3257
3258 return;
3259 }
3260 else
3261 {
3262 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
c3b7224a 3263 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
3264 }
3265 }
3266 }
3267 else
3268 {
c3b7224a 3269 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3270 }
3271}
3272
3273/* Handle cache. */
1c0d3aa6 3274static void
c3b7224a 3275s3_do_cache (char *str)
1c0d3aa6 3276{
c3b7224a 3277 s3_skip_whitespace (str);
1c0d3aa6 3278
c3b7224a 3279 if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3280 {
3281 return;
3282 }
3283 else
3284 {
3285 int cache_op;
3286
c3b7224a
NC
3287 cache_op = (s3_inst.instruction >> 20) & 0x1F;
3288 sprintf (s3_inst.name, "cache %d", cache_op);
1c0d3aa6
NC
3289 }
3290
3291 if (*str == '[')
3292 {
3293 str++;
c3b7224a 3294 s3_skip_whitespace (str);
1c0d3aa6 3295
c3b7224a 3296 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3297 return;
3298
c3b7224a 3299 s3_skip_whitespace (str);
1c0d3aa6
NC
3300
3301 /* cache op, [rA] */
c3b7224a 3302 if (s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6 3303 {
c3b7224a 3304 s3_SET_INSN_ERROR (NULL);
1c0d3aa6
NC
3305 if (*str != ']')
3306 {
c3b7224a 3307 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3308 return;
3309 }
3310 str++;
3311 }
3312 /* cache op, [rA, simm15] */
3313 else
3314 {
c3b7224a 3315 if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
1c0d3aa6
NC
3316 {
3317 return;
3318 }
3319
c3b7224a 3320 s3_skip_whitespace (str);
1c0d3aa6
NC
3321 if (*str++ != ']')
3322 {
c3b7224a 3323 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3324 return;
3325 }
3326 }
3327
c3b7224a 3328 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3329 return;
3330 }
3331 else
3332 {
c3b7224a 3333 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3334 }
3335}
3336
3337static void
c3b7224a 3338s3_do_crdcrscrsimm5 (char *str)
1c0d3aa6
NC
3339{
3340 char *strbak;
3341
3342 strbak = str;
c3b7224a 3343 s3_skip_whitespace (str);
1c0d3aa6 3344
c3b7224a
NC
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)
1c0d3aa6
NC
3351 {
3352 str = strbak;
3353 /* cop1 cop_code20. */
c3b7224a 3354 if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
1c0d3aa6
NC
3355 return;
3356 }
3357 else
3358 {
c3b7224a 3359 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
1c0d3aa6
NC
3360 return;
3361 }
3362
c3b7224a 3363 s3_end_of_line (str);
1c0d3aa6
NC
3364}
3365
3366/* Handle ldc/stc. */
3367static void
c3b7224a 3368s3_do_ldst_cop (char *str)
1c0d3aa6 3369{
c3b7224a 3370 s3_skip_whitespace (str);
1c0d3aa6 3371
c3b7224a
NC
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))
1c0d3aa6
NC
3374 return;
3375
3376 if (*str == '[')
3377 {
3378 str++;
c3b7224a 3379 s3_skip_whitespace (str);
1c0d3aa6 3380
c3b7224a 3381 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3382 return;
3383
c3b7224a 3384 s3_skip_whitespace (str);
1c0d3aa6
NC
3385
3386 if (*str++ != ']')
3387 {
c3b7224a 3388 if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
1c0d3aa6
NC
3389 return;
3390
c3b7224a 3391 s3_skip_whitespace (str);
1c0d3aa6
NC
3392 if (*str++ != ']')
3393 {
c3b7224a 3394 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3395 return;
3396 }
3397 }
3398
c3b7224a 3399 s3_end_of_line (str);
1c0d3aa6
NC
3400 }
3401 else
c3b7224a 3402 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3403}
3404
3405static void
c3b7224a 3406s3_do16_ldst_insn (char *str)
1c0d3aa6 3407{
f9e53abc 3408 int conflict_reg = 0;
c3b7224a 3409 s3_skip_whitespace (str);
1c0d3aa6 3410
c3b7224a 3411 if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3412 return;
3413
3414 if (*str == '[')
3415 {
1c0d3aa6
NC
3416
3417 str++;
c3b7224a 3418 s3_skip_whitespace (str);
1c0d3aa6 3419
c3b7224a 3420 if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
1c0d3aa6 3421 return;
c3b7224a
NC
3422 if (conflict_reg&0x8)
3423 {
3424 sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
f9e53abc
NC
3425 s3_inst.error = s3_err_msg;
3426 return;
c3b7224a 3427 }
1c0d3aa6 3428
c3b7224a 3429 s3_skip_whitespace (str);
f9e53abc 3430
c3b7224a 3431 if (*str == ']')
1c0d3aa6 3432 {
c3b7224a
NC
3433 str++;
3434 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 3435 return;
1c0d3aa6
NC
3436 }
3437 else
3438 {
c3b7224a
NC
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)
f9e53abc
NC
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]);
c3b7224a
NC
3467 s3_inst.error = s3_err_msg;
3468 return;
3469 }
f9e53abc 3470 if (value & 0x3)
c3b7224a
NC
3471 {
3472 sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value);
f9e53abc
NC
3473 s3_inst.error = s3_err_msg;
3474 return;
c3b7224a
NC
3475 }
3476
f9e53abc 3477 value >>= 2;
c3b7224a
NC
3478 s3_inst.instruction |= value;
3479 }
1c0d3aa6
NC
3480 }
3481 }
3482 else
3483 {
c3b7224a 3484 sprintf (s3_err_msg, _("missing ["));
f9e53abc
NC
3485 s3_inst.error = s3_err_msg;
3486 return;
1c0d3aa6
NC
3487 }
3488}
3489
1c0d3aa6 3490static void
c3b7224a 3491s3_do_lw48 (char *str)
1c0d3aa6 3492{
c3b7224a 3493 bfd_signed_vma val = 0;
1c0d3aa6 3494
c3b7224a 3495 s3_skip_whitespace (str);
1c0d3aa6 3496
c3b7224a
NC
3497 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3498 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3499 return;
3500
c3b7224a
NC
3501 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3502 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 3503 {
c3b7224a 3504 return;
1c0d3aa6
NC
3505 }
3506
c3b7224a
NC
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 }
1c0d3aa6 3514
c3b7224a
NC
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 }
1c0d3aa6 3523
c3b7224a
NC
3524 val &= 0xffffffff;
3525 val >>= 2;
3526 s3_inst.instruction |= (val << 7);
1c0d3aa6 3527
c3b7224a
NC
3528 /* Set reloc type. */
3529 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
1c0d3aa6 3530
1c0d3aa6
NC
3531}
3532
3533static void
c3b7224a 3534s3_do_sw48 (char *str)
1c0d3aa6 3535{
c3b7224a 3536 bfd_signed_vma val = 0;
1c0d3aa6 3537
c3b7224a 3538 s3_skip_whitespace (str);
1c0d3aa6 3539
c3b7224a
NC
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;
1c0d3aa6 3543
c3b7224a
NC
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 }
1c0d3aa6 3549
c3b7224a
NC
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 }
1c0d3aa6 3557
c3b7224a
NC
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)))
1c0d3aa6 3562 {
c3b7224a
NC
3563 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3564 return;
3565 }
1c0d3aa6 3566
c3b7224a
NC
3567 val &= 0xffffffff;
3568 val >>= 2;
3569 s3_inst.instruction |= (val << 7);
1c0d3aa6 3570
c3b7224a
NC
3571 /* Set reloc type. */
3572 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3573}
1c0d3aa6 3574
c3b7224a
NC
3575static void
3576s3_do_ldi48 (char *str)
3577{
3578 bfd_signed_vma val;
1c0d3aa6 3579
c3b7224a 3580 s3_skip_whitespace (str);
1c0d3aa6 3581
c3b7224a
NC
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;
1c0d3aa6 3590 }
c3b7224a
NC
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
3607static void
3608s3_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
3616static void
3617s3_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
3630static void
3631s3_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
f9e53abc 3644static void
c3b7224a
NC
3645s3_do_mbitclr (char *str)
3646{
3647 int val;
3648 s3_skip_whitespace (str);
3649
3650 if (*str != '[')
3651 {
3652 sprintf (s3_err_msg, _("missing ["));
f9e53abc 3653 s3_inst.error = s3_err_msg;
c3b7224a
NC
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 ]"));
f9e53abc 3674 s3_inst.error = s3_err_msg;
c3b7224a
NC
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)
f9e53abc
NC
3685 | (((val >> 1 ) & 0x7) << 7)
3686 | (((val >> 4 ) & 0x1f) << 20);
c3b7224a
NC
3687}
3688
f9e53abc 3689static void
c3b7224a
NC
3690s3_do_mbitset (char *str)
3691{
3692 int val;
3693 s3_skip_whitespace (str);
3694
3695 if (*str != '[')
1c0d3aa6 3696 {
c3b7224a 3697 sprintf (s3_err_msg, _("missing ["));
f9e53abc 3698 s3_inst.error = s3_err_msg;
c3b7224a
NC
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 ]"));
f9e53abc 3719 s3_inst.error = s3_err_msg;
c3b7224a
NC
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)
f9e53abc
NC
3730 | (((val >> 1 ) & 0x7) << 7)
3731 | (((val >> 4 ) & 0x1f) << 20);
c3b7224a
NC
3732}
3733
3734static void
3735s3_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
f9e53abc 3742 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3743 return;
3744}
3745
3746static void
3747s3_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
f9e53abc 3754 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3755 return;
3756}
3757
3758static void
3759s3_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
f9e53abc 3763 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3764 return;
3765}
3766
3767static void
3768s3_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
f9e53abc 3776 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3777 return;
3778
3779 /* 0: indicate 32.
33eaf5de 3780 1: invalid value.
c3b7224a 3781 2: to 31: normal value. */
f9e53abc 3782 val = s3_inst.instruction & 0x1f;
c3b7224a
NC
3783 if (val == 1)
3784 {
f9e53abc
NC
3785 s3_inst.error = _("imm5 should >= 2");
3786 return;
c3b7224a
NC
3787 }
3788 if (reg >= 32)
3789 {
3790 s3_inst.error = _("reg should <= 31");
3791 return;
3792 }
3793}
3794
3795static void
3796s3_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
f9e53abc 3804 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3805 return;
3806
3807 /* 0: indicate 32.
33eaf5de 3808 1: invalid value.
c3b7224a
NC
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 }
f9e53abc 3822 else
c3b7224a
NC
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;
1c0d3aa6
NC
3831 }
3832}
3833
3834/* Handle lcb/lcw/lce/scb/scw/sce. */
3835static void
c3b7224a 3836s3_do_ldst_unalign (char *str)
1c0d3aa6
NC
3837{
3838 int conflict_reg;
3839
c3b7224a 3840 if (s3_university_version == 1)
1c0d3aa6 3841 {
c3b7224a 3842 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
1c0d3aa6
NC
3843 return;
3844 }
3845
c3b7224a 3846 s3_skip_whitespace (str);
1c0d3aa6
NC
3847
3848 /* lcb/scb [rA]+. */
3849 if (*str == '[')
3850 {
3851 str++;
c3b7224a 3852 s3_skip_whitespace (str);
1c0d3aa6 3853
c3b7224a 3854 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3855 return;
3856
3857 if (*str++ == ']')
3858 {
3859 if (*str++ != '+')
3860 {
c3b7224a 3861 s3_inst.error = _("missing +");
1c0d3aa6
NC
3862 return;
3863 }
3864 }
3865 else
3866 {
c3b7224a 3867 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3868 return;
3869 }
3870
c3b7224a 3871 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3872 return;
3873 }
3874 /* lcw/lce/scb/sce rD, [rA]+. */
3875 else
3876 {
c3b7224a
NC
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))
1c0d3aa6
NC
3879 {
3880 return;
3881 }
3882
c3b7224a 3883 s3_skip_whitespace (str);
1c0d3aa6
NC
3884 if (*str++ == '[')
3885 {
3886 int reg;
3887
c3b7224a
NC
3888 s3_skip_whitespace (str);
3889 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
3890 {
3891 return;
3892 }
3893
3894 /* Conflicts can occur on stores as well as loads. */
3895 conflict_reg = (conflict_reg == reg);
c3b7224a 3896 s3_skip_whitespace (str);
1c0d3aa6
NC
3897 if (*str++ == ']')
3898 {
c3b7224a 3899 unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
1c0d3aa6
NC
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 {
c3b7224a 3912 s3_inst.error = _("missing +");
1c0d3aa6
NC
3913 return;
3914 }
3915
c3b7224a 3916 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3917 return;
3918 }
3919 else
3920 {
c3b7224a 3921 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3922 return;
3923 }
3924 }
3925 else
3926 {
c3b7224a 3927 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3928 return;
3929 }
3930 }
3931}
3932
3933/* Handle alw/asw. */
3934static void
c3b7224a 3935s3_do_ldst_atomic (char *str)
1c0d3aa6 3936{
c3b7224a 3937 if (s3_university_version == 1)
1c0d3aa6 3938 {
c3b7224a 3939 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
1c0d3aa6
NC
3940 return;
3941 }
3942
c3b7224a 3943 s3_skip_whitespace (str);
1c0d3aa6 3944
c3b7224a
NC
3945 if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3946 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3947 {
3948 return;
3949 }
3950 else
3951 {
3952
c3b7224a 3953 s3_skip_whitespace (str);
1c0d3aa6
NC
3954 if (*str++ == '[')
3955 {
3956 int reg;
3957
c3b7224a
NC
3958 s3_skip_whitespace (str);
3959 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
3960 {
3961 return;
3962 }
3963
c3b7224a 3964 s3_skip_whitespace (str);
1c0d3aa6
NC
3965 if (*str++ != ']')
3966 {
c3b7224a 3967 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3968 return;
3969 }
3970
c3b7224a 3971 s3_end_of_line (str);
1c0d3aa6
NC
3972 }
3973 else
c3b7224a 3974 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3975 }
3976}
3977
3978static void
c3b7224a 3979s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
f9e53abc
NC
3980 struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
3981 symbolS *add_symbol)
1c0d3aa6
NC
3982{
3983 int i;
3984 char *p;
3985 fixS *fixp = NULL;
b3549761 3986 fixS *cur_fixp = NULL;
1c0d3aa6 3987 long where;
c3b7224a 3988 struct s3_score_it inst_main;
1c0d3aa6 3989
c3b7224a 3990 memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
1c0d3aa6
NC
3991
3992 /* Adjust instruction opcode and to be relaxed instruction opcode. */
c3b7224a 3993 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
1c0d3aa6
NC
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;
c3b7224a 3999 var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
f9e53abc 4000 s3_GET_INSN_CLASS (var_insts[i].type));
1c0d3aa6
NC
4001 }
4002
4003 /* Check data dependency. */
c3b7224a 4004 s3_handle_dependency (&inst_main);
1c0d3aa6
NC
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);
c3b7224a 4019 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
1c0d3aa6
NC
4020
4021 if (inst_main.reloc.type != BFD_RELOC_NONE)
c3b7224a 4022 fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
f9e53abc 4023 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
1c0d3aa6 4024
b3549761
NC
4025 frag_now->tc_frag_data.fixp = fixp;
4026 cur_fixp = frag_now->tc_frag_data.fixp;
1c0d3aa6
NC
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 {
c3b7224a 4040 fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
f9e53abc
NC
4041 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4042 var_insts[i].reloc.type);
1c0d3aa6
NC
4043 if (fixp)
4044 {
b3549761
NC
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 }
1c0d3aa6
NC
4055 }
4056 }
4057 }
4058
c3b7224a
NC
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,
f9e53abc 4061 0, inst_main.size, 0), add_symbol, 0, NULL);
1c0d3aa6
NC
4062
4063 /* Write fr_var part.
c3b7224a 4064 no calling s3_gen_insn_frag, no fixS will be generated. */
1c0d3aa6
NC
4065 for (i = 0; i < var_num; i++)
4066 {
c3b7224a 4067 s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
1c0d3aa6
NC
4068 p += var_insts[i].size;
4069 }
4070 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4071 s3_inst.bwarn = -1;
1c0d3aa6
NC
4072}
4073
c3b7224a 4074/* Build a relax frag for la instruction when generating s3_PIC,
1c0d3aa6 4075 external symbol first and local symbol second. */
1c0d3aa6 4076static void
c3b7224a 4077s3_build_la_pic (int reg_rd, expressionS exp)
1c0d3aa6
NC
4078{
4079 symbolS *add_symbol = exp.X_add_symbol;
4080 offsetT add_number = exp.X_add_number;
c3b7224a
NC
4081 struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4082 struct s3_score_it var_insts[s3_RELAX_INST_NUM];
1c0d3aa6
NC
4083 int fix_num = 0;
4084 int var_num = 0;
c3b7224a 4085 char tmp[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6
NC
4086 int r1_bak;
4087
c3b7224a
NC
4088 r1_bak = s3_nor1;
4089 s3_nor1 = 0;
1c0d3aa6
NC
4090
4091 if (add_number == 0)
4092 {
4093 fix_num = 1;
4094 var_num = 2;
4095
f9e53abc 4096 /* For an external symbol, only one insn is generated;
8fce5f8c 4097 For a local symbol, two insns are generated. */
1c0d3aa6 4098 /* Fix part
8fce5f8c 4099 For an external symbol: lw rD, <sym>($gp)
f9e53abc 4100 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
8d1015a8 4101 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
5b7c81bd 4102 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4103 return;
4104
c3b7224a
NC
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));
1c0d3aa6
NC
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) */
c3b7224a
NC
4113 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4114 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
8d1015a8 4115 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
5b7c81bd 4116 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4117 return;
4118
c3b7224a
NC
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);
1c0d3aa6
NC
4121 }
4122 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4123 {
4124 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
8d1015a8 4125 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
5b7c81bd 4126 if (s3_append_insn (tmp, true) == (int) s3_FAIL)
1c0d3aa6
NC
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> */
48903831 4134 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
5b7c81bd 4135 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4136 return;
4137
c3b7224a 4138 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4139
4140 /* Var part
4141 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
8d1015a8
AM
4142 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd,
4143 S_GET_NAME (add_symbol), (int) add_number);
5b7c81bd 4144 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4145 return;
4146
c3b7224a
NC
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);
1c0d3aa6
NC
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) */
8d1015a8 4156 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
5b7c81bd 4157 if (s3_append_insn (tmp, true) == (int) s3_FAIL)
1c0d3aa6
NC
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> */
48903831 4165 sprintf (tmp, "ldis r1, %d", hi);
5b7c81bd 4166 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4167 return;
4168
c3b7224a 4169 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4170
4171 /* Var part
4172 For a local symbol: ldis r1, HI%<constant>
33eaf5de 4173 but, if lo is out of 16 bit, make hi plus 1 */
1c0d3aa6
NC
4174 if ((lo < -0x8000) || (lo > 0x7fff))
4175 {
4176 hi += 1;
4177 }
48903831 4178 sprintf (tmp, "ldis_pic r1, %d", hi);
5b7c81bd 4179 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4180 return;
4181
c3b7224a
NC
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);
1c0d3aa6
NC
4184
4185 /* Insn 3 */
4186 fix_num = 1;
4187 var_num = 1;
4188 /* Fix part
4189 For an external symbol: ori r1, LO%<constant> */
48903831 4190 sprintf (tmp, "ori r1, %d", lo);
5b7c81bd 4191 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4192 return;
4193
c3b7224a 4194 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4195
4196 /* Var part
4197 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
8d1015a8 4198 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo);
5b7c81bd 4199 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
1c0d3aa6
NC
4200 return;
4201
c3b7224a
NC
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);
1c0d3aa6
NC
4204
4205 /* Insn 4: add rD, rD, r1 */
48903831 4206 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
5b7c81bd 4207 if (s3_append_insn (tmp, true) == (int) s3_FAIL)
1c0d3aa6
NC
4208 return;
4209
f9e53abc
NC
4210 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4211 s3_inst.bwarn = -1;
1c0d3aa6
NC
4212 }
4213
c3b7224a 4214 s3_nor1 = r1_bak;
1c0d3aa6
NC
4215}
4216
4217/* Handle la. */
4218static void
c3b7224a 4219s3_do_macro_la_rdi32 (char *str)
1c0d3aa6
NC
4220{
4221 int reg_rd;
4222
c3b7224a
NC
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)
1c0d3aa6
NC
4226 {
4227 return;
4228 }
4229 else
4230 {
c3b7224a 4231 /* Save str. */
1c0d3aa6 4232 char *keep_data = str;
c3b7224a
NC
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;
1c0d3aa6
NC
4250
4251 /* la rd, simm16. */
c3b7224a 4252 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
1c0d3aa6 4253 {
c3b7224a 4254 s3_end_of_line (str);
1c0d3aa6
NC
4255 return;
4256 }
4257 /* la rd, imm32 or la rd, label. */
4258 else
4259 {
c3b7224a
NC
4260 s3_SET_INSN_ERROR (NULL);
4261 /* Reset str. */
1c0d3aa6 4262 str = keep_data;
c3b7224a
NC
4263 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4264 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
4265 {
4266 return;
4267 }
4268 else
4269 {
c3b7224a 4270 if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol))
14119072 4271 {
48903831 4272 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
5b7c81bd 4273 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
1c0d3aa6
NC
4274 return;
4275
48903831 4276 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
5b7c81bd 4277 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
1c0d3aa6
NC
4278 return;
4279 }
4280 else
4281 {
9c2799c2 4282 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a 4283 s3_build_la_pic (reg_rd, s3_inst.reloc.exp);
1c0d3aa6
NC
4284 }
4285
4286 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4287 s3_inst.bwarn = -1;
1c0d3aa6
NC
4288 }
4289 }
4290 }
4291}
4292
4293/* Handle li. */
4294static void
c3b7224a
NC
4295s3_do_macro_li_rdi32 (char *str)
4296{
1c0d3aa6
NC
4297
4298 int reg_rd;
4299
c3b7224a
NC
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)
1c0d3aa6
NC
4303 {
4304 return;
4305 }
4306 else
4307 {
c3b7224a 4308 /* Save str. */
1c0d3aa6
NC
4309 char *keep_data = str;
4310
c3b7224a
NC
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
1c0d3aa6 4327 /* li rd, simm16. */
c3b7224a 4328 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
1c0d3aa6 4329 {
c3b7224a 4330 s3_end_of_line (str);
1c0d3aa6
NC
4331 return;
4332 }
4333 /* li rd, imm32. */
4334 else
4335 {
c3b7224a 4336 char append_str[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4337
c3b7224a 4338 /* Reset str. */
1c0d3aa6
NC
4339 str = keep_data;
4340
c3b7224a
NC
4341 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4342 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
4343 {
4344 return;
4345 }
c3b7224a 4346 else if (s3_inst.reloc.exp.X_add_symbol)
1c0d3aa6 4347 {
c3b7224a 4348 s3_inst.error = _("li rd label isn't correct instruction form");
1c0d3aa6
NC
4349 return;
4350 }
4351 else
4352 {
48903831 4353 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
1c0d3aa6 4354
5b7c81bd 4355 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
1c0d3aa6
NC
4356 return;
4357 else
4358 {
48903831 4359 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
5b7c81bd 4360 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
1c0d3aa6
NC
4361 return;
4362
4363 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4364 s3_inst.bwarn = -1;
1c0d3aa6
NC
4365 }
4366 }
4367 }
4368 }
4369}
4370
4371/* Handle mul/mulu/div/divu/rem/remu. */
4372static void
c3b7224a 4373s3_do_macro_mul_rdrsrs (char *str)
1c0d3aa6
NC
4374{
4375 int reg_rd;
4376 int reg_rs1;
4377 int reg_rs2;
4378 char *backupstr;
c3b7224a 4379 char append_str[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4380
c3b7224a
NC
4381 if (s3_university_version == 1)
4382 as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV);
1c0d3aa6
NC
4383
4384 strcpy (append_str, str);
4385 backupstr = append_str;
c3b7224a
NC
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))
1c0d3aa6 4390 {
c3b7224a 4391 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
4392 return;
4393 }
4394
c3b7224a 4395 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
1c0d3aa6
NC
4396 {
4397 /* rem/remu rA, rB is error format. */
c3b7224a 4398 if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0)
1c0d3aa6 4399 {
c3b7224a 4400 s3_SET_INSN_ERROR (s3_BAD_ARGS);
1c0d3aa6
NC
4401 }
4402 else
4403 {
c3b7224a
NC
4404 s3_SET_INSN_ERROR (NULL);
4405 s3_do_rsrs (str);
1c0d3aa6
NC
4406 }
4407 return;
4408 }
4409 else
4410 {
c3b7224a
NC
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))
1c0d3aa6
NC
4414 {
4415 return;
4416 }
4417 else
4418 {
c3b7224a 4419 char append_str1[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4420
c3b7224a 4421 if (strcmp (s3_inst.name, "rem") == 0)
1c0d3aa6 4422 {
48903831
NC
4423 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4424 sprintf (append_str1, "mfceh r%d", reg_rd);
1c0d3aa6 4425 }
c3b7224a 4426 else if (strcmp (s3_inst.name, "remu") == 0)
1c0d3aa6 4427 {
48903831
NC
4428 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4429 sprintf (append_str1, "mfceh r%d", reg_rd);
1c0d3aa6
NC
4430 }
4431 else
4432 {
c3b7224a 4433 sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2);
48903831 4434 sprintf (append_str1, "mfcel r%d", reg_rd);
1c0d3aa6
NC
4435 }
4436
4437 /* Output mul/mulu or div/divu or rem/remu. */
5b7c81bd 4438 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
1c0d3aa6
NC
4439 return;
4440
4441 /* Output mfcel or mfceh. */
5b7c81bd 4442 if (s3_append_insn (append_str1, true) == (int) s3_FAIL)
1c0d3aa6
NC
4443 return;
4444
4445 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4446 s3_inst.bwarn = -1;
1c0d3aa6
NC
4447 }
4448 }
4449}
4450
4451static void
c3b7224a 4452s3_exp_macro_ldst_abs (char *str)
1c0d3aa6
NC
4453{
4454 int reg_rd;
4455 char *backupstr, *tmp;
c3b7224a
NC
4456 char append_str[s3_MAX_LITERAL_POOL_SIZE];
4457 char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4458 struct s3_score_it inst_backup;
1c0d3aa6
NC
4459 int r1_bak = 0;
4460
c3b7224a
NC
4461 r1_bak = s3_nor1;
4462 s3_nor1 = 0;
4463 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4464
4465 strcpy (verifystr, str);
4466 backupstr = verifystr;
c3b7224a
NC
4467 s3_skip_whitespace (backupstr);
4468 if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
4469 return;
4470
4471 tmp = backupstr;
c3b7224a 4472 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
1c0d3aa6
NC
4473 return;
4474
4475 backupstr = tmp;
48903831 4476 sprintf (append_str, "li r1 %s", backupstr);
5b7c81bd 4477 s3_append_insn (append_str, true);
1c0d3aa6 4478
c3b7224a 4479 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
48903831 4480 sprintf (append_str, " r%d, [r1,0]", reg_rd);
c3b7224a 4481 s3_do_ldst_insn (append_str);
1c0d3aa6 4482
c3b7224a 4483 s3_nor1 = r1_bak;
1c0d3aa6 4484}
f9e53abc 4485
c3b7224a
NC
4486/* Handle bcmpeq / bcmpne */
4487static void
4488s3_do_macro_bcmp (char *str)
1c0d3aa6 4489{
c3b7224a 4490 int reg_a , reg_b;
861d8651
AM
4491 char *keep_data;
4492 size_t keep_data_size;
4493 int i;
c3b7224a 4494 struct s3_score_it inst_expand[2];
02fb2970 4495 struct s3_score_it inst_main;
c3b7224a 4496
f9e53abc 4497 memset (inst_expand, 0, sizeof inst_expand);
c3b7224a
NC
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)
f9e53abc 4503 return;
861d8651
AM
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
f9e53abc
NC
4509 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4510 ||reg_b == 0
c3b7224a 4511 || s3_end_of_line (str) == (int) s3_FAIL)
861d8651 4512 goto out;
c3b7224a
NC
4513 else if (s3_inst.reloc.exp.X_add_symbol == 0)
4514 {
4515 s3_inst.error = _("lacking label ");
861d8651 4516 goto out;
c3b7224a
NC
4517 }
4518 else
1c0d3aa6 4519 {
861d8651 4520 char *append_str = keep_data + keep_data_size;
c3b7224a 4521 s3_SET_INSN_ERROR (NULL);
f9e53abc 4522
c3b7224a
NC
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;
1c0d3aa6 4526
c3b7224a 4527 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
f9e53abc
NC
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;
c3b7224a
NC
4531
4532 /* Check and set offset. */
4533 if (((val & 0xfffffe00) != 0)
f9e53abc 4534 && ((val & 0xfffffe00) != 0xfffffe00))
1c0d3aa6 4535 {
c3b7224a
NC
4536 /* support bcmp --> cmp!+beq (bne) */
4537 if (s3_score_pic == s3_NO_PIC)
4538 {
861d8651 4539 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
5b7c81bd 4540 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
861d8651
AM
4541 goto out;
4542 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4543 memcpy (append_str, "beq ", 4);
861d8651 4544 else
a05e3e20
L
4545 memcpy (append_str, "bne ", 4);
4546 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
5b7c81bd 4547 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
861d8651 4548 goto out;
f9e53abc
NC
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;
861d8651 4556 goto out;
1c0d3aa6 4557 }
c3b7224a 4558 else
1c0d3aa6 4559 {
c3b7224a
NC
4560 val >>= 1;
4561 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
4562 | (((val >> 1) & 0x7) << 7)
4563 | (((val >> 4) & 0x1f) << 20);
1c0d3aa6
NC
4564 }
4565
c3b7224a
NC
4566 /* Backup s3_inst. */
4567 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6 4568
f9e53abc 4569 if (s3_score_pic == s3_NO_PIC)
c3b7224a 4570 {
861d8651 4571 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
5b7c81bd 4572 if (s3_append_insn (append_str, false) == (int) s3_FAIL)
861d8651
AM
4573 goto out;
4574 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
f9e53abc 4575
861d8651 4576 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4577 memcpy (append_str, "beq ", 4);
861d8651 4578 else
a05e3e20
L
4579 memcpy (append_str, "bne ", 4);
4580 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
5b7c81bd 4581 if (s3_append_insn (append_str, false) == (int) s3_FAIL)
861d8651
AM
4582 goto out;
4583 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
c3b7224a
NC
4584 }
4585 else
4586 {
9c2799c2 4587 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
4588 }
4589 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4590 inst_main.type = Insn_BCMP;
1c0d3aa6 4591
c3b7224a
NC
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));
1c0d3aa6 4594
c3b7224a 4595 for (i = 0; i < 2; i++)
f9e53abc 4596 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
c3b7224a
NC
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)
f9e53abc
NC
4602 {
4603 if (!frag_now->tc_frag_data.is_insn)
4604 frag_wane (frag_now);
4605 frag_new (0);
4606 }
c3b7224a 4607 frag_grow (20);
1c0d3aa6 4608
c3b7224a
NC
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);
1c0d3aa6 4613
c3b7224a 4614 if (inst_main.reloc.type != BFD_RELOC_NONE)
f9e53abc
NC
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 }
c3b7224a
NC
4619#ifdef OBJ_ELF
4620 dwarf2_emit_insn (inst_main.size);
4621#endif
1c0d3aa6 4622
c3b7224a
NC
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);
1c0d3aa6 4628
c3b7224a
NC
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;
1c0d3aa6 4635
8fce5f8c 4636 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4637 s3_inst.bwarn = -1;
f9e53abc 4638 }
861d8651
AM
4639 out:
4640 free (keep_data);
c3b7224a
NC
4641}
4642
4643/* Handle bcmpeqz / bcmpnez */
4644static void
4645s3_do_macro_bcmpz (char *str)
4646{
f9e53abc 4647 int reg_a;
861d8651
AM
4648 char *keep_data;
4649 size_t keep_data_size;
4650 int i;
c3b7224a
NC
4651 struct s3_score_it inst_expand[2];
4652 struct s3_score_it inst_main;
4653
f9e53abc 4654 memset (inst_expand, 0, sizeof inst_expand);
c3b7224a
NC
4655 s3_skip_whitespace (str);
4656 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
f9e53abc 4657 || s3_skip_past_comma (&str) == (int) s3_FAIL)
c3b7224a 4658 return;
c3b7224a 4659
861d8651
AM
4660 keep_data_size = strlen (str) + 1;
4661 keep_data = xmalloc (keep_data_size * 2 + 13);
4662 memcpy (keep_data, str, keep_data_size);
f9e53abc
NC
4663
4664 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4665 || s3_end_of_line (str) == (int) s3_FAIL)
861d8651 4666 goto out;
c3b7224a
NC
4667 else if (s3_inst.reloc.exp.X_add_symbol == 0)
4668 {
4669 s3_inst.error = _("lacking label ");
861d8651 4670 goto out;
c3b7224a
NC
4671 }
4672 else
4673 {
861d8651 4674 char *append_str = keep_data + keep_data_size;
c3b7224a
NC
4675 s3_SET_INSN_ERROR (NULL);
4676 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
f9e53abc 4677 s3_inst.reloc.pc_rel = 1;
c3b7224a
NC
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. */
f9e53abc 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;
c3b7224a
NC
4682
4683 /* Check and set offset. */
4684 if (((val & 0xfffffe00) != 0)
f9e53abc 4685 && ((val & 0xfffffe00) != 0xfffffe00))
c3b7224a
NC
4686 {
4687 if (s3_score_pic == s3_NO_PIC)
4688 {
861d8651 4689 sprintf (append_str, "cmpi! r%d, 0", reg_a);
5b7c81bd 4690 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
861d8651
AM
4691 goto out;
4692 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4693 memcpy (append_str, "beq ", 4);
861d8651 4694 else
a05e3e20
L
4695 memcpy (append_str, "bne ", 4);
4696 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
5b7c81bd 4697 if (s3_append_insn (append_str, true) == (int) s3_FAIL)
861d8651 4698 goto out;
c3b7224a
NC
4699 }
4700 else
4701 {
9c2799c2 4702 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
4703 }
4704 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4705 s3_inst.bwarn = -1;
861d8651 4706 goto out;
c3b7224a
NC
4707 }
4708 else
4709 {
4710 val >>= 1;
4711 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
4712 | (((val >> 1) & 0x7) << 7)
4713 | (((val >> 4) & 0x1f) << 20);
c3b7224a
NC
4714 }
4715
4716 /* Backup s3_inst. */
4717 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
f9e53abc
NC
4718
4719 if (s3_score_pic == s3_NO_PIC)
c3b7224a 4720 {
861d8651 4721 sprintf (append_str, "cmpi! r%d, 0", reg_a);
5b7c81bd 4722 if (s3_append_insn (append_str, false) == (int) s3_FAIL)
861d8651
AM
4723 goto out;
4724 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4725 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4726 memcpy (append_str, "beq ", 4);
861d8651 4727 else
a05e3e20
L
4728 memcpy (append_str, "bne ", 4);
4729 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
5b7c81bd 4730 if (s3_append_insn (append_str, false) == (int) s3_FAIL)
861d8651
AM
4731 goto out;
4732 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
c3b7224a
NC
4733 }
4734 else
4735 {
9c2799c2 4736 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
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++)
f9e53abc
NC
4745 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction ,
4746 s3_GET_INSN_CLASS (inst_expand[i].type));
c3b7224a
NC
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)
f9e53abc
NC
4751 {
4752 if (!frag_now->tc_frag_data.is_insn)
4753 frag_wane (frag_now);
4754 frag_new (0);
4755 }
c3b7224a
NC
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)
f9e53abc
NC
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 }
c3b7224a
NC
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;
f9e53abc 4787 }
861d8651
AM
4788 out:
4789 free (keep_data);
c3b7224a
NC
4790}
4791
4792static int
4793s3_nopic_need_relax (symbolS * sym, int before_relaxing)
4794{
4795 if (sym == NULL)
4796 return 0;
4797 else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0)
4798 {
4799 const char *symname;
4800 const char *segname;
4801
4802 /* Find out whether this symbol can be referenced off the $gp
4803 register. It can be if it is smaller than the -G size or if
4804 it is in the .sdata or .sbss section. Certain symbols can
4805 not be referenced off the $gp, although it appears as though
4806 they can. */
4807 symname = S_GET_NAME (sym);
4808 if (symname != (const char *)NULL
4809 && (strcmp (symname, "eprol") == 0
4810 || strcmp (symname, "etext") == 0
4811 || strcmp (symname, "_gp") == 0
4812 || strcmp (symname, "edata") == 0
4813 || strcmp (symname, "_fbss") == 0
4814 || strcmp (symname, "_fdata") == 0
4815 || strcmp (symname, "_ftext") == 0
4816 || strcmp (symname, "end") == 0
4817 || strcmp (symname, GP_DISP_LABEL) == 0))
4818 {
4819 return 1;
4820 }
4821 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
f9e53abc
NC
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)))
c3b7224a
NC
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
d34049e8
ML
4835 && !startswith (segname, ".sdata.")
4836 && !startswith (segname, ".gnu.linkonce.s."));
c3b7224a
NC
4837 }
4838 /* We are not optimizing for the $gp register. */
4839 else
4840 return 1;
4841}
4842
4843/* Build a relax frag for lw/st instruction when generating s3_PIC,
4844 external symbol first and local symbol second. */
4845static void
4846s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4847{
4848 symbolS *add_symbol = exp.X_add_symbol;
4849 int add_number = exp.X_add_number;
4850 struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4851 struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4852 int fix_num = 0;
4853 int var_num = 0;
4854 char tmp[s3_MAX_LITERAL_POOL_SIZE];
4855 int r1_bak;
4856
4857 r1_bak = s3_nor1;
4858 s3_nor1 = 0;
4859
4860 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4861 {
4862 fix_num = 1;
4863 var_num = 2;
4864
4865 /* For an external symbol, two insns are generated;
4866 For a local symbol, three insns are generated. */
4867 /* Fix part
4868 For an external symbol: lw rD, <sym>($gp)
f9e53abc 4869 (BFD_RELOC_SCORE_GOT15) */
8d1015a8 4870 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol));
5b7c81bd 4871 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
c3b7224a
NC
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));
8d1015a8 4882 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol));
5b7c81bd 4883 if (s3_append_insn (tmp, false) == (int) s3_FAIL)
c3b7224a
NC
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);
5b7c81bd 4891 if (s3_append_insn (tmp, true) == (int) s3_FAIL)
c3b7224a
NC
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)");
8fce5f8c 4900 return;
1c0d3aa6
NC
4901 }
4902
c3b7224a 4903 s3_nor1 = r1_bak;
1c0d3aa6
NC
4904}
4905
4906static void
c3b7224a 4907s3_do_macro_ldst_label (char *str)
1c0d3aa6
NC
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;
c3b7224a
NC
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;
1c0d3aa6 4921
c3b7224a 4922 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4923 strcpy (verifystr, str);
4924 backup_str = verifystr;
4925
c3b7224a
NC
4926 s3_skip_whitespace (backup_str);
4927 if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
4928 return;
4929
c3b7224a 4930 if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL)
1c0d3aa6
NC
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 {
c3b7224a
NC
4938 s3_inst.type = Rd_rvalueRs_preSI12;
4939 s3_do_ldst_insn (str);
1c0d3aa6
NC
4940 return;
4941 }
4942
4943 /* Ld/st rD, imm. */
4944 absolute_value = backup_str;
c3b7224a
NC
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)
1c0d3aa6 4959 {
c3b7224a 4960 s3_inst.error = _("end on line error");
1c0d3aa6
NC
4961 return;
4962 }
4963 else
4964 {
c3b7224a 4965 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 4966 {
c3b7224a
NC
4967 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4968 s3_exp_macro_ldst_abs (str);
1c0d3aa6
NC
4969 return;
4970 }
4971 }
4972
4973 /* Ld/st rD, label. */
c3b7224a 4974 s3_inst.type = Rd_rvalueRs_SI15;
1c0d3aa6 4975 backup_str = absolute_value;
c3b7224a
NC
4976 if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL)
4977 || (s3_end_of_line (backup_str) == (int) s3_FAIL))
1c0d3aa6
NC
4978 {
4979 return;
4980 }
4981 else
4982 {
c3b7224a 4983 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 4984 {
c3b7224a
NC
4985 if (!s3_inst.error)
4986 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
4987
4988 return;
4989 }
4990
c3b7224a 4991 if (s3_score_pic == s3_PIC)
1c0d3aa6 4992 {
8fce5f8c 4993 int ldst_idx = 0;
c3b7224a 4994 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
d3ce72d0
NC
4995 s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp,
4996 s3_score_ldst_insns[ldst_idx * 3 + 0].template_name);
8fce5f8c 4997 return;
1c0d3aa6
NC
4998 }
4999 else
5000 {
c3b7224a 5001 if ((s3_inst.reloc.exp.X_add_number <= 0x3fff)
f9e53abc
NC
5002 && (s3_inst.reloc.exp.X_add_number >= -0x4000)
5003 && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1)))
1c0d3aa6
NC
5004 {
5005 int ldst_idx = 0;
5006
5007 /* Assign the real opcode. */
c3b7224a
NC
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;
1c0d3aa6
NC
5015 ldst_gp_p = 1;
5016 }
5017 }
5018 }
5019
c3b7224a
NC
5020 /* Backup s3_inst. */
5021 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
5022 r1_bak = s3_nor1;
5023 s3_nor1 = 0;
1c0d3aa6
NC
5024
5025 /* Determine which instructions should be output. */
48903831
NC
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);
1c0d3aa6
NC
5029
5030 /* Generate three instructions.
5031 la r1, label
5032 ld/st rd, [r1, 0] */
5033 for (i = 0; i < 3; i++)
5034 {
5b7c81bd 5035 if (s3_append_insn (append_str[i], false) == (int) s3_FAIL)
1c0d3aa6
NC
5036 return;
5037
c3b7224a 5038 memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
5039 }
5040
5041 if (ldst_gp_p)
5042 {
5043 char *p;
5044
5045 /* Adjust instruction opcode and to be relaxed instruction opcode. */
c3b7224a
NC
5046 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
5047
f9e53abc
NC
5048 /* relax lw rd, label -> ldis rs, imm16
5049 ori rd, imm16
5050 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
c3b7224a
NC
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
1c0d3aa6
NC
5056 inst_main.type = Insn_GP;
5057
5058 for (i = 0; i < 3; i++)
f9e53abc 5059 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
c3b7224a 5060 s3_GET_INSN_CLASS (inst_expand[i].type));
1c0d3aa6
NC
5061
5062 /* Check data dependency. */
c3b7224a 5063 s3_handle_dependency (&inst_main);
1c0d3aa6
NC
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);
c3b7224a 5077 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
1c0d3aa6
NC
5078
5079 if (inst_main.reloc.type != BFD_RELOC_NONE)
5080 {
c3b7224a 5081 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
f9e53abc 5082 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
1c0d3aa6
NC
5083 }
5084
5085#ifdef OBJ_ELF
5086 dwarf2_emit_insn (inst_main.size);
5087#endif
5088
c3b7224a 5089 /* s3_GP instruction can not do optimization, only can do relax between
1c0d3aa6 5090 1 instruction and 3 instructions. */
c3b7224a
NC
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),
1c0d3aa6
NC
5093 inst_main.reloc.exp.X_add_symbol, 0, NULL);
5094
5095 /* Write fr_var part.
c3b7224a
NC
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);
1c0d3aa6 5098 p += inst_expand[0].size;
c3b7224a 5099 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
1c0d3aa6 5100 p += inst_expand[1].size;
c3b7224a 5101
f9e53abc
NC
5102 /* relax lw rd, label -> ldis rs, imm16
5103 ori rd, imm16
5104 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
c3b7224a
NC
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);
1c0d3aa6
NC
5109 }
5110 else
5111 {
c3b7224a
NC
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);
1c0d3aa6 5115 }
c3b7224a 5116 s3_nor1 = r1_bak;
1c0d3aa6
NC
5117
5118 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 5119 s3_inst.bwarn = -1;
1c0d3aa6
NC
5120}
5121
5122static void
c3b7224a 5123s3_do_lw_pic (char *str)
1c0d3aa6
NC
5124{
5125 int reg_rd;
5126
c3b7224a
NC
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))
1c0d3aa6
NC
5132 {
5133 return;
5134 }
5135 else
5136 {
c3b7224a 5137 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5138 {
c3b7224a
NC
5139 if (!s3_inst.error)
5140 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
5141
5142 return;
5143 }
5144
c3b7224a
NC
5145 s3_inst.instruction |= s3_GP << 15;
5146 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
1c0d3aa6
NC
5147 }
5148}
5149
5150static void
c3b7224a 5151s3_do_empty (char *str)
1c0d3aa6
NC
5152{
5153 str = str;
c3b7224a 5154 if (s3_university_version == 1)
1c0d3aa6 5155 {
c3b7224a
NC
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))
1c0d3aa6 5160 {
c3b7224a 5161 s3_inst.error = s3_ERR_FOR_SCORE5U_MMU;
1c0d3aa6
NC
5162 return;
5163 }
5164 }
c3b7224a 5165 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
5166 return;
5167
c3b7224a 5168 if (s3_inst.relax_inst != 0x8000)
1c0d3aa6 5169 {
c3b7224a 5170 if (s3_inst.type == NO_OPD)
1c0d3aa6 5171 {
c3b7224a 5172 s3_inst.relax_size = 2;
1c0d3aa6
NC
5173 }
5174 else
5175 {
c3b7224a 5176 s3_inst.relax_size = 4;
1c0d3aa6
NC
5177 }
5178 }
5179}
5180
5181static void
c3b7224a
NC
5182s3_do16_int (char *str)
5183{
5184 s3_skip_whitespace (str);
5185 return;
5186}
5187
5188static void
5189s3_do_jump (char *str)
1c0d3aa6
NC
5190{
5191 char *save_in;
1c0d3aa6 5192
c3b7224a
NC
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)
1c0d3aa6
NC
5196 return;
5197
c3b7224a 5198 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5199 {
c3b7224a 5200 s3_inst.error = _("lacking label ");
1c0d3aa6
NC
5201 return;
5202 }
5203
c3b7224a 5204 if (!(s3_inst.reloc.exp.X_add_number >= -16777216
f9e53abc 5205 && s3_inst.reloc.exp.X_add_number <= 16777215))
1c0d3aa6 5206 {
c3b7224a 5207 s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
1c0d3aa6
NC
5208 return;
5209 }
5210
5211 save_in = input_line_pointer;
5212 input_line_pointer = str;
c3b7224a
NC
5213 s3_inst.reloc.type = BFD_RELOC_SCORE_JMP;
5214 s3_inst.reloc.pc_rel = 1;
1c0d3aa6
NC
5215 input_line_pointer = save_in;
5216}
5217
5218static void
c3b7224a 5219s3_do_branch (char *str)
1c0d3aa6 5220{
c3b7224a
NC
5221 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5222 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
5223 {
5224 return;
5225 }
c3b7224a 5226 else if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5227 {
c3b7224a 5228 s3_inst.error = _("lacking label ");
1c0d3aa6
NC
5229 return;
5230 }
c3b7224a 5231 else if (!(s3_inst.reloc.exp.X_add_number >= -524288
f9e53abc 5232 && s3_inst.reloc.exp.X_add_number <= 524287))
1c0d3aa6 5233 {
33eaf5de 5234 s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19-1");
1c0d3aa6
NC
5235 return;
5236 }
5237
c3b7224a
NC
5238 s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5239 s3_inst.reloc.pc_rel = 1;
1c0d3aa6
NC
5240
5241 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
c3b7224a 5242 s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5);
1c0d3aa6 5243
41c55c87 5244 /* Compute 16 bit branch instruction. */
c3b7224a
NC
5245 if ((s3_inst.relax_inst != 0x8000)
5246 && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511))
1c0d3aa6 5247 {
c3b7224a
NC
5248 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */
5249 s3_inst.relax_size = 2;
1c0d3aa6
NC
5250 }
5251 else
5252 {
c3b7224a 5253 s3_inst.relax_inst = 0x8000;
1c0d3aa6 5254 }
1c0d3aa6
NC
5255}
5256
5257static void
c3b7224a 5258s3_do16_branch (char *str)
1c0d3aa6 5259{
c3b7224a 5260 if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
f9e53abc 5261 || s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
5262 {
5263 ;
5264 }
c3b7224a 5265 else if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5266 {
c3b7224a 5267 s3_inst.error = _("lacking label");
1c0d3aa6 5268 }
c3b7224a 5269 else if (!(s3_inst.reloc.exp.X_add_number >= -512
f9e53abc 5270 && s3_inst.reloc.exp.X_add_number <= 511))
1c0d3aa6 5271 {
c3b7224a 5272 s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
1c0d3aa6
NC
5273 }
5274 else
5275 {
c3b7224a
NC
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;
1c0d3aa6
NC
5281 }
5282}
5283
c3b7224a 5284/* Return true if the given symbol should be considered local for s3_PIC. */
5b7c81bd 5285static bool
c3b7224a 5286s3_pic_need_relax (symbolS *sym, asection *segtype)
1c0d3aa6 5287{
c3b7224a 5288 asection *symsec;
5b7c81bd 5289 bool linkonce;
1c0d3aa6 5290
c3b7224a
NC
5291 /* Handle the case of a symbol equated to another symbol. */
5292 while (symbol_equated_reloc_p (sym))
1c0d3aa6 5293 {
c3b7224a 5294 symbolS *n;
1c0d3aa6 5295
c3b7224a
NC
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;
1c0d3aa6 5302 }
1c0d3aa6 5303
c3b7224a 5304 symsec = S_GET_SEGMENT (sym);
1c0d3aa6 5305
c3b7224a 5306 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5b7c81bd 5307 linkonce = false;
c3b7224a 5308 if (symsec != segtype && ! S_IS_LOCAL (sym))
1c0d3aa6 5309 {
fd361982 5310 if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0)
5b7c81bd 5311 linkonce = true;
1c0d3aa6 5312
c3b7224a 5313 /* The GNU toolchain uses an extension for ELF: a section
f9e53abc
NC
5314 beginning with the magic string .gnu.linkonce is a linkonce
5315 section. */
d34049e8 5316 if (startswith (segment_name (symsec), ".gnu.linkonce"))
5b7c81bd 5317 linkonce = true;
1c0d3aa6 5318 }
1c0d3aa6 5319
c3b7224a 5320 /* This must duplicate the test in adjust_reloc_syms. */
45dfa85a
AM
5321 return (!bfd_is_und_section (symsec)
5322 && !bfd_is_abs_section (symsec)
5323 && !bfd_is_com_section (symsec)
f9e53abc 5324 && !linkonce
c3b7224a
NC
5325#ifdef OBJ_ELF
5326 /* A global or weak symbol is treated as external. */
5327 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5328 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5329#endif
5330 );
5331}
1c0d3aa6 5332
c3b7224a
NC
5333static void
5334s3_parse_pce_inst (char *insnstr)
1c0d3aa6 5335{
c3b7224a
NC
5336 char c;
5337 char *p;
5338 char first[s3_MAX_LITERAL_POOL_SIZE];
5339 char second[s3_MAX_LITERAL_POOL_SIZE];
5340 struct s3_score_it pec_part_1;
1c0d3aa6 5341
c3b7224a
NC
5342 /* Get first part string of PCE. */
5343 p = strstr (insnstr, "||");
5344 c = *p;
5345 *p = '\0';
5346 sprintf (first, "%s", insnstr);
1c0d3aa6 5347
c3b7224a
NC
5348 /* Get second part string of PCE. */
5349 *p = c;
5350 p += 2;
5351 sprintf (second, "%s", p);
5352
5b7c81bd 5353 s3_parse_16_32_inst (first, false);
c3b7224a
NC
5354 if (s3_inst.error)
5355 return;
5356
5357 memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst));
5358
5b7c81bd 5359 s3_parse_16_32_inst (second, false);
c3b7224a
NC
5360 if (s3_inst.error)
5361 return;
5362
5363 if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE))
f9e53abc
NC
5364 || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE))
5365 || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE)))
1c0d3aa6 5366 {
33eaf5de 5367 s3_inst.error = _("pce instruction error (16 bit || 16 bit).");
cb580a26 5368 sprintf (s3_inst.str, "%s", insnstr);
c3b7224a 5369 return;
1c0d3aa6
NC
5370 }
5371
c3b7224a
NC
5372 if (!s3_inst.error)
5373 s3_gen_insn_frag (&pec_part_1, &s3_inst);
1c0d3aa6
NC
5374}
5375
c3b7224a
NC
5376/* s3: dsp. */
5377static void
5378s3_do16_dsp (char *str)
1c0d3aa6 5379{
c3b7224a 5380 int rd = 0;
1c0d3aa6 5381
f9e53abc 5382 /* Check 3d. */
c3b7224a 5383 if (s3_score3d == 0)
1c0d3aa6 5384 {
c3b7224a
NC
5385 s3_inst.error = _("score3d instruction.");
5386 return;
1c0d3aa6
NC
5387 }
5388
c3b7224a 5389 s3_skip_whitespace (str);
1c0d3aa6 5390
c3b7224a
NC
5391 if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL
5392 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 5393 {
c3b7224a 5394 return;
1c0d3aa6 5395 }
1c0d3aa6 5396 else
1c0d3aa6 5397 {
c3b7224a
NC
5398 s3_inst.relax_inst |= rd << 20;
5399 s3_inst.relax_size = 4;
1c0d3aa6 5400 }
1c0d3aa6
NC
5401}
5402
c3b7224a
NC
5403static void
5404s3_do16_dsp2 (char *str)
1c0d3aa6 5405{
f9e53abc 5406 /* Check 3d. */
c3b7224a 5407 if (s3_score3d == 0)
1c0d3aa6 5408 {
c3b7224a
NC
5409 s3_inst.error = _("score3d instruction.");
5410 return;
1c0d3aa6
NC
5411 }
5412
c3b7224a 5413 s3_skip_whitespace (str);
1c0d3aa6 5414
c3b7224a
NC
5415 if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
5416 || s3_skip_past_comma (&str) == (int) s3_FAIL
5417 || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
5418 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 5419 {
c3b7224a 5420 return;
1c0d3aa6
NC
5421 }
5422 else
5423 {
c3b7224a
NC
5424 s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20)
5425 | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10);
5426 s3_inst.relax_size = 4;
1c0d3aa6 5427 }
1c0d3aa6
NC
5428}
5429
c3b7224a
NC
5430static void
5431s3_do_dsp (char *str)
1c0d3aa6 5432{
f9e53abc 5433 /* Check 3d. */
c3b7224a 5434 if (s3_score3d == 0)
1c0d3aa6 5435 {
c3b7224a
NC
5436 s3_inst.error = _("score3d instruction.");
5437 return;
1c0d3aa6
NC
5438 }
5439
c3b7224a
NC
5440 s3_skip_whitespace (str);
5441
5442 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5443 || s3_skip_past_comma (&str) == (int) s3_FAIL
5444 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5445 || s3_end_of_line (str) == (int) s3_FAIL)
5446 return;
1c0d3aa6 5447
c3b7224a 5448 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
1c0d3aa6 5449 {
c3b7224a
NC
5450 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5451 s3_inst.relax_size = 2;
1c0d3aa6
NC
5452 }
5453 else
c3b7224a
NC
5454 s3_inst.relax_inst = 0x8000;
5455}
5456
5457static void
5458s3_do_dsp2 (char *str)
5459{
5460 int reg;
5461
f9e53abc 5462 /* Check 3d. */
c3b7224a 5463 if (s3_score3d == 0)
1c0d3aa6 5464 {
c3b7224a
NC
5465 s3_inst.error = _("score3d instruction.");
5466 return;
1c0d3aa6
NC
5467 }
5468
c3b7224a 5469 s3_skip_whitespace (str);
1c0d3aa6 5470
c3b7224a
NC
5471 if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5472 || s3_skip_past_comma (&str) == (int) s3_FAIL
5473 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5474 || s3_skip_past_comma (&str) == (int) s3_FAIL
5475 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5476 || s3_end_of_line (str) == (int) s3_FAIL)
5477 {
5478 return;
1c0d3aa6
NC
5479 }
5480 else
5481 {
c3b7224a
NC
5482 /* Check mulr, mulur rd is even number. */
5483 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
f9e53abc 5484 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
c3b7224a 5485 && (reg % 2))
1c0d3aa6 5486 {
c3b7224a
NC
5487 s3_inst.error = _("rd must be even number.");
5488 return;
1c0d3aa6
NC
5489 }
5490
c3b7224a
NC
5491 if ((((s3_inst.instruction >> 15) & 0x10) == 0)
5492 && (((s3_inst.instruction >> 10) & 0x10) == 0)
5493 && (((s3_inst.instruction >> 20) & 0x10) == 0)
5494 && (s3_inst.relax_inst != 0x8000)
5495 && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
1c0d3aa6 5496 {
c3b7224a
NC
5497 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
5498 | (((s3_inst.instruction >> 15) & 0xf) << 4);
5499 s3_inst.relax_size = 2;
1c0d3aa6
NC
5500 }
5501 else
c3b7224a
NC
5502 {
5503 s3_inst.relax_inst = 0x8000;
5504 }
1c0d3aa6 5505 }
1c0d3aa6
NC
5506}
5507
c3b7224a
NC
5508static void
5509s3_do_dsp3 (char *str)
1c0d3aa6 5510{
f9e53abc 5511 /* Check 3d. */
c3b7224a
NC
5512 if (s3_score3d == 0)
5513 {
5514 s3_inst.error = _("score3d instruction.");
5515 return;
5516 }
1c0d3aa6 5517
c3b7224a 5518 s3_skip_whitespace (str);
1c0d3aa6 5519
c3b7224a
NC
5520 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5521 || s3_skip_past_comma (&str) == (int) s3_FAIL
5522 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5523 || s3_end_of_line (str) == (int) s3_FAIL)
5524 return;
1c0d3aa6 5525
c3b7224a 5526 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
1c0d3aa6 5527 {
c3b7224a
NC
5528 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5529 s3_inst.relax_size = 2;
1c0d3aa6 5530 }
c3b7224a
NC
5531 else
5532 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
5533}
5534
1c0d3aa6 5535
c3b7224a
NC
5536/* If we change section we must dump the literal pool first. */
5537static void
5538s3_s_score_bss (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 5539{
c3b7224a
NC
5540 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5541 demand_empty_rest_of_line ();
1c0d3aa6
NC
5542}
5543
c3b7224a
NC
5544static void
5545s3_s_score_text (int ignore)
1c0d3aa6 5546{
c3b7224a
NC
5547 obj_elf_text (ignore);
5548 record_alignment (now_seg, 2);
1c0d3aa6
NC
5549}
5550
c3b7224a
NC
5551static void
5552s3_score_s_section (int ignore)
1c0d3aa6 5553{
c3b7224a 5554 obj_elf_section (ignore);
fd361982 5555 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5556 record_alignment (now_seg, 2);
5557
1c0d3aa6
NC
5558}
5559
c3b7224a
NC
5560static void
5561s3_s_change_sec (int sec)
1c0d3aa6 5562{
c3b7224a 5563 segT seg;
1c0d3aa6 5564
c3b7224a
NC
5565#ifdef OBJ_ELF
5566 /* The ELF backend needs to know that we are changing sections, so
5567 that .previous works correctly. We could do something like check
5568 for an obj_section_change_hook macro, but that might be confusing
5569 as it would not be appropriate to use it in the section changing
5570 functions in read.c, since obj-elf.c intercepts those. FIXME:
5571 This should be cleaner, somehow. */
5572 obj_elf_section_change_hook ();
5573#endif
5574 switch (sec)
1c0d3aa6 5575 {
c3b7224a
NC
5576 case 'r':
5577 seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
a4dd6c97
AM
5578 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY
5579 | SEC_RELOC | SEC_DATA));
c3b7224a
NC
5580 if (strcmp (TARGET_OS, "elf") != 0)
5581 record_alignment (seg, 4);
5582 demand_empty_rest_of_line ();
5583 break;
5584 case 's':
5585 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
a4dd6c97
AM
5586 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
5587 | SEC_DATA | SEC_SMALL_DATA));
c3b7224a
NC
5588 if (strcmp (TARGET_OS, "elf") != 0)
5589 record_alignment (seg, 4);
5590 demand_empty_rest_of_line ();
5591 break;
1c0d3aa6 5592 }
1c0d3aa6
NC
5593}
5594
c3b7224a
NC
5595static void
5596s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
1c0d3aa6 5597{
c3b7224a 5598 long mask, off;
1c0d3aa6 5599
c3b7224a 5600 if (s3_cur_proc_ptr == (s3_procS *) NULL)
1c0d3aa6 5601 {
c3b7224a
NC
5602 as_warn (_(".mask outside of .ent"));
5603 demand_empty_rest_of_line ();
5604 return;
1c0d3aa6 5605 }
c3b7224a
NC
5606 if (get_absolute_expression_and_terminator (&mask) != ',')
5607 {
5608 as_warn (_("Bad .mask directive"));
5609 --input_line_pointer;
5610 demand_empty_rest_of_line ();
5611 return;
5612 }
5613 off = get_absolute_expression ();
5614 s3_cur_proc_ptr->reg_mask = mask;
5615 s3_cur_proc_ptr->reg_offset = off;
5616 demand_empty_rest_of_line ();
1c0d3aa6
NC
5617}
5618
c3b7224a
NC
5619static symbolS *
5620s3_get_symbol (void)
1c0d3aa6 5621{
c3b7224a
NC
5622 int c;
5623 char *name;
5624 symbolS *p;
1c0d3aa6 5625
d02603dc 5626 c = get_symbol_name (&name);
c3b7224a 5627 p = (symbolS *) symbol_find_or_make (name);
d02603dc 5628 (void) restore_line_pointer (c);
c3b7224a 5629 return p;
1c0d3aa6
NC
5630}
5631
c3b7224a
NC
5632static long
5633s3_get_number (void)
1c0d3aa6 5634{
c3b7224a
NC
5635 int negative = 0;
5636 long val = 0;
1c0d3aa6 5637
c3b7224a 5638 if (*input_line_pointer == '-')
1c0d3aa6 5639 {
c3b7224a
NC
5640 ++input_line_pointer;
5641 negative = 1;
1c0d3aa6 5642 }
c3b7224a
NC
5643 if (!ISDIGIT (*input_line_pointer))
5644 as_bad (_("expected simple number"));
5645 if (input_line_pointer[0] == '0')
1c0d3aa6 5646 {
c3b7224a 5647 if (input_line_pointer[1] == 'x')
1c0d3aa6 5648 {
c3b7224a
NC
5649 input_line_pointer += 2;
5650 while (ISXDIGIT (*input_line_pointer))
1c0d3aa6 5651 {
c3b7224a
NC
5652 val <<= 4;
5653 val |= hex_value (*input_line_pointer++);
1c0d3aa6 5654 }
c3b7224a 5655 return negative ? -val : val;
1c0d3aa6
NC
5656 }
5657 else
5658 {
c3b7224a
NC
5659 ++input_line_pointer;
5660 while (ISDIGIT (*input_line_pointer))
1c0d3aa6 5661 {
c3b7224a
NC
5662 val <<= 3;
5663 val |= *input_line_pointer++ - '0';
1c0d3aa6 5664 }
c3b7224a 5665 return negative ? -val : val;
1c0d3aa6 5666 }
c3b7224a
NC
5667 }
5668 if (!ISDIGIT (*input_line_pointer))
5669 {
5670 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5671 as_warn (_("invalid number"));
5672 return -1;
5673 }
5674 while (ISDIGIT (*input_line_pointer))
5675 {
5676 val *= 10;
5677 val += *input_line_pointer++ - '0';
5678 }
5679 return negative ? -val : val;
5680}
5681
5682/* The .aent and .ent directives. */
5683static void
5684s3_s_score_ent (int aent)
5685{
5686 symbolS *symbolP;
5687 int maybe_text;
5688
5689 symbolP = s3_get_symbol ();
5690 if (*input_line_pointer == ',')
5691 ++input_line_pointer;
5692 SKIP_WHITESPACE ();
5693 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5694 s3_get_number ();
5695
fd361982 5696 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5697 maybe_text = 1;
5698 else
5699 maybe_text = 0;
c3b7224a
NC
5700 if (!maybe_text)
5701 as_warn (_(".ent or .aent not in text section."));
5702 if (!aent && s3_cur_proc_ptr)
5703 as_warn (_("missing .end"));
5704 if (!aent)
5705 {
5706 s3_cur_proc_ptr = &s3_cur_proc;
5707 s3_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5708 s3_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5709 s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5710 s3_cur_proc_ptr->leaf = 0xdeafbeaf;
5711 s3_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5712 s3_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5713 s3_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5714 s3_cur_proc_ptr->isym = symbolP;
5715 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5716 ++s3_numprocs;
5717 if (debug_type == DEBUG_STABS)
5718 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5719 }
5720 demand_empty_rest_of_line ();
5721}
5722
5723static void
5724s3_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5725{
5726 char *backupstr;
5727 char str[30];
5728 long val;
5729 int i = 0;
5730
5731 backupstr = input_line_pointer;
5732
5733#ifdef OBJ_ELF
5734 if (s3_cur_proc_ptr == (s3_procS *) NULL)
5735 {
5736 as_warn (_(".frame outside of .ent"));
5737 demand_empty_rest_of_line ();
5738 return;
5739 }
5740 s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5741 SKIP_WHITESPACE ();
5742 s3_skip_past_comma (&backupstr);
5743 while (*backupstr != ',')
5744 {
5745 str[i] = *backupstr;
5746 i++;
5747 backupstr++;
5748 }
5749 str[i] = '\0';
5750 val = atoi (str);
5751
5752 SKIP_WHITESPACE ();
5753 s3_skip_past_comma (&backupstr);
5754 s3_cur_proc_ptr->frame_offset = val;
5755 s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5756
5757 SKIP_WHITESPACE ();
5758 s3_skip_past_comma (&backupstr);
5759 i = 0;
5760 while (*backupstr != '\n')
5761 {
5762 str[i] = *backupstr;
5763 i++;
5764 backupstr++;
5765 }
5766 str[i] = '\0';
5767 val = atoi (str);
5768 s3_cur_proc_ptr->leaf = val;
5769 SKIP_WHITESPACE ();
5770 s3_skip_past_comma (&backupstr);
5771
5772#endif /* OBJ_ELF */
5773 while (input_line_pointer != backupstr)
5774 input_line_pointer++;
5775}
5776
5777/* The .end directive. */
5778static void
5779s3_s_score_end (int x ATTRIBUTE_UNUSED)
5780{
5781 symbolS *p;
5782 int maybe_text;
5783
5784 /* Generate a .pdr section. */
5785 segT saved_seg = now_seg;
5786 subsegT saved_subseg = now_subseg;
c3b7224a
NC
5787 expressionS exp;
5788 char *fragp;
5789
5790 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5791 {
5792 p = s3_get_symbol ();
5793 demand_empty_rest_of_line ();
5794 }
5795 else
5796 p = NULL;
5797
fd361982 5798 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5799 maybe_text = 1;
5800 else
5801 maybe_text = 0;
c3b7224a
NC
5802
5803 if (!maybe_text)
5804 as_warn (_(".end not in text section"));
5805 if (!s3_cur_proc_ptr)
5806 {
5807 as_warn (_(".end directive without a preceding .ent directive."));
5808 demand_empty_rest_of_line ();
5809 return;
5810 }
5811 if (p != NULL)
5812 {
9c2799c2 5813 gas_assert (S_GET_NAME (p));
c3b7224a
NC
5814 if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym)))
5815 as_warn (_(".end symbol does not match .ent symbol."));
5816 if (debug_type == DEBUG_STABS)
5817 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5818 }
5819 else
5820 as_warn (_(".end directive missing or unknown symbol"));
5821
5822 if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5823 (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5824 (s3_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5825 (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5826 (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5827
5828 else
5829 {
f9e53abc 5830 (void) frag_now_fix ();
9c2799c2 5831 gas_assert (s3_pdr_seg);
c3b7224a
NC
5832 subseg_set (s3_pdr_seg, 0);
5833 /* Write the symbol. */
5834 exp.X_op = O_symbol;
5835 exp.X_add_symbol = p;
5836 exp.X_add_number = 0;
5837 emit_expr (&exp, 4);
5838 fragp = frag_more (7 * 4);
5839 md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4);
5840 md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4);
5841 md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4);
5842 md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4);
5843 md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4);
5844 md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4);
5845 md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4);
5846 subseg_set (saved_seg, saved_subseg);
5847
5848 }
5849 s3_cur_proc_ptr = NULL;
5850}
5851
5852/* Handle the .set pseudo-op. */
5853static void
5854s3_s_score_set (int x ATTRIBUTE_UNUSED)
5855{
5856 int i = 0;
5857 char name[s3_MAX_LITERAL_POOL_SIZE];
5858 char * orig_ilp = input_line_pointer;
5859
5860 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5861 {
5862 name[i] = (char) * input_line_pointer;
5863 i++;
5864 ++input_line_pointer;
5865 }
5866
5867 name[i] = '\0';
5868
5869 if (strcmp (name, "nwarn") == 0)
5870 {
5871 s3_warn_fix_data_dependency = 0;
5872 }
5873 else if (strcmp (name, "fixdd") == 0)
5874 {
5875 s3_fix_data_dependency = 1;
5876 }
5877 else if (strcmp (name, "nofixdd") == 0)
5878 {
5879 s3_fix_data_dependency = 0;
5880 }
5881 else if (strcmp (name, "r1") == 0)
5882 {
5883 s3_nor1 = 0;
5884 }
5885 else if (strcmp (name, "nor1") == 0)
5886 {
5887 s3_nor1 = 1;
5888 }
5889 else if (strcmp (name, "optimize") == 0)
5890 {
5891 s3_g_opt = 1;
5892 }
5893 else if (strcmp (name, "volatile") == 0)
5894 {
5895 s3_g_opt = 0;
5896 }
5897 else if (strcmp (name, "pic") == 0)
5898 {
5899 s3_score_pic = s3_PIC;
5900 }
5901 else
5902 {
5903 input_line_pointer = orig_ilp;
5904 s_set (0);
5905 }
5906}
5907
5908/* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the
5909 $gp register for the function based on the function address, which is in the register
5910 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5911 specially by the linker. The result is:
5912 ldis gp, %hi(GP_DISP_LABEL)
5913 ori gp, %low(GP_DISP_LABEL)
5914 add gp, gp, .cpload argument
5915 The .cpload argument is normally r29. */
5916static void
5917s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5918{
5919 int reg;
5920 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5921
5922 /* If we are not generating s3_PIC code, .cpload is ignored. */
5923 if (s3_score_pic == s3_NO_PIC)
5924 {
5925 s_ignore (0);
5926 return;
5927 }
5928
5929 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5930 return;
5931
5932 demand_empty_rest_of_line ();
5933
5934 sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL);
5b7c81bd 5935 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5936 return;
5937
5938 sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL);
5b7c81bd 5939 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5940 return;
5941
5942 sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg);
5b7c81bd 5943 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5944 return;
5945}
5946
5947/* Handle the .cprestore pseudo-op. This stores $gp into a given
5948 offset from $sp. The offset is remembered, and after making a s3_PIC
5949 call $gp is restored from that location. */
5950static void
5951s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5952{
5953 int reg;
5954 int cprestore_offset;
5955 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5956
5957 /* If we are not generating s3_PIC code, .cprestore is ignored. */
5958 if (s3_score_pic == s3_NO_PIC)
5959 {
5960 s_ignore (0);
5961 return;
5962 }
5963
5964 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5965 || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL)
5966 {
5967 return;
5968 }
5969
5970 cprestore_offset = get_absolute_expression ();
5971
5972 if (cprestore_offset <= 0x3fff)
5973 {
5974 sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset);
5b7c81bd 5975 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5976 return;
5977 }
5978 else
5979 {
5980 int r1_bak;
5981
5982 r1_bak = s3_nor1;
5983 s3_nor1 = 0;
5984
5985 sprintf (insn_str, "li r1, %d", cprestore_offset);
5b7c81bd 5986 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5987 return;
5988
5989 sprintf (insn_str, "add r1, r1, r%d", reg);
5b7c81bd 5990 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5991 return;
5992
5993 sprintf (insn_str, "sw r%d, [r1]", s3_GP);
5b7c81bd 5994 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
5995 return;
5996
5997 s3_nor1 = r1_bak;
5998 }
5999
6000 demand_empty_rest_of_line ();
6001}
6002
6003/* Handle the .gpword pseudo-op. This is used when generating s3_PIC
6004 code. It generates a 32 bit s3_GP relative reloc. */
6005static void
6006s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6007{
6008 expressionS ex;
6009 char *p;
6010
6011 /* When not generating s3_PIC code, this is treated as .word. */
6012 if (s3_score_pic == s3_NO_PIC)
6013 {
6014 cons (4);
6015 return;
6016 }
6017 expression (&ex);
6018 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6019 {
6020 as_bad (_("Unsupported use of .gpword"));
6021 ignore_rest_of_line ();
6022 }
6023 p = frag_more (4);
6024 s3_md_number_to_chars (p, (valueT) 0, 4);
5b7c81bd 6025 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, false, BFD_RELOC_GPREL32);
c3b7224a
NC
6026 demand_empty_rest_of_line ();
6027}
6028
6029/* Handle the .cpadd pseudo-op. This is used when dealing with switch
6030 tables in s3_PIC code. */
6031static void
6032s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6033{
6034 int reg;
6035 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
6036
6037 /* If we are not generating s3_PIC code, .cpload is ignored. */
6038 if (s3_score_pic == s3_NO_PIC)
6039 {
6040 s_ignore (0);
6041 return;
6042 }
6043
6044 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
6045 {
6046 return;
6047 }
6048 demand_empty_rest_of_line ();
6049
6050 /* Add $gp to the register named as an argument. */
6051 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP);
5b7c81bd 6052 if (s3_append_insn (insn_str, true) == (int) s3_FAIL)
c3b7224a
NC
6053 return;
6054}
6055
6056#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
f9e53abc
NC
6057#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6058 do \
6059 { \
6060 if ((SIZE) >= 8) \
6061 (P2VAR) = 3; \
6062 else if ((SIZE) >= 4) \
6063 (P2VAR) = 2; \
6064 else if ((SIZE) >= 2) \
6065 (P2VAR) = 1; \
6066 else \
6067 (P2VAR) = 0; \
6068 } \
c3b7224a
NC
6069 while (0)
6070#endif
1c0d3aa6 6071
c3b7224a
NC
6072static void
6073s3_s_score_lcomm (int bytes_p)
6074{
6075 char *name;
6076 char c;
6077 char *p;
6078 int temp;
6079 symbolS *symbolP;
6080 segT current_seg = now_seg;
6081 subsegT current_subseg = now_subseg;
6082 const int max_alignment = 15;
6083 int align = 0;
6084 segT bss_seg = bss_section;
6085 int needs_align = 0;
6086
d02603dc 6087 c = get_symbol_name (&name);
c3b7224a 6088 p = input_line_pointer;
d02603dc 6089 (void) restore_line_pointer (c);
c3b7224a
NC
6090
6091 if (name == p)
6092 {
6093 as_bad (_("expected symbol name"));
6094 discard_rest_of_line ();
6095 return;
6096 }
6097
6098 SKIP_WHITESPACE ();
6099
6100 /* Accept an optional comma after the name. The comma used to be
6101 required, but Irix 5 cc does not generate it. */
6102 if (*input_line_pointer == ',')
6103 {
6104 ++input_line_pointer;
6105 SKIP_WHITESPACE ();
6106 }
6107
6108 if (is_end_of_line[(unsigned char)*input_line_pointer])
6109 {
6110 as_bad (_("missing size expression"));
6111 return;
6112 }
6113
6114 if ((temp = get_absolute_expression ()) < 0)
6115 {
6116 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6117 ignore_rest_of_line ();
6118 return;
6119 }
6120
6121#if defined (TC_SCORE)
6122 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6123 {
6124 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
fd361982
AM
6125 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6126 {
6127 bss_seg = subseg_new (".sbss", 1);
6128 seg_info (bss_seg)->bss = 1;
a4dd6c97 6129 if (!bfd_set_section_flags (bss_seg, SEC_ALLOC | SEC_SMALL_DATA))
fd361982
AM
6130 as_warn (_("error setting flags for \".sbss\": %s"),
6131 bfd_errmsg (bfd_get_error ()));
fd361982 6132 }
c3b7224a 6133 }
1c0d3aa6 6134#endif
1c0d3aa6 6135
c3b7224a
NC
6136 SKIP_WHITESPACE ();
6137 if (*input_line_pointer == ',')
6138 {
6139 ++input_line_pointer;
6140 SKIP_WHITESPACE ();
6141
6142 if (is_end_of_line[(unsigned char)*input_line_pointer])
1c0d3aa6 6143 {
c3b7224a
NC
6144 as_bad (_("missing alignment"));
6145 return;
1c0d3aa6 6146 }
1c0d3aa6
NC
6147 else
6148 {
c3b7224a
NC
6149 align = get_absolute_expression ();
6150 needs_align = 1;
1c0d3aa6 6151 }
1c0d3aa6 6152 }
1c0d3aa6 6153
c3b7224a
NC
6154 if (!needs_align)
6155 {
6156 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
1c0d3aa6 6157
c3b7224a
NC
6158 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6159 if (align)
6160 record_alignment (bss_seg, align);
6161 }
1c0d3aa6 6162
c3b7224a
NC
6163 if (needs_align)
6164 {
6165 if (bytes_p)
6166 {
6167 /* Convert to a power of 2. */
6168 if (align != 0)
6169 {
6170 unsigned int i;
1c0d3aa6 6171
c3b7224a
NC
6172 for (i = 0; align != 0; align >>= 1, ++i)
6173 ;
6174 align = i - 1;
6175 }
6176 }
6177
6178 if (align > max_alignment)
6179 {
6180 align = max_alignment;
6181 as_warn (_("alignment too large; %d assumed"), align);
6182 }
6183 else if (align < 0)
6184 {
6185 align = 0;
6186 as_warn (_("alignment negative; 0 assumed"));
6187 }
6188
6189 record_alignment (bss_seg, align);
6190 }
6191 else
1c0d3aa6 6192 {
c3b7224a
NC
6193 /* Assume some objects may require alignment on some systems. */
6194#if defined (TC_ALPHA) && ! defined (VMS)
6195 if (temp > 1)
6196 {
6197 align = ffs (temp) - 1;
6198 if (temp % (1 << align))
6199 abort ();
6200 }
6201#endif
6202 }
1c0d3aa6 6203
c3b7224a
NC
6204 *p = 0;
6205 symbolP = symbol_find_or_make (name);
6206 *p = c;
1c0d3aa6 6207
c3b7224a 6208 if (
a8eb42a8 6209#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
f9e53abc
NC
6210 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6211 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
c3b7224a 6212#endif
f9e53abc 6213 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
c3b7224a
NC
6214 {
6215 char *pfrag;
1c0d3aa6 6216
c3b7224a 6217 subseg_set (bss_seg, 1);
1c0d3aa6 6218
c3b7224a
NC
6219 if (align)
6220 frag_align (align, 0, 0);
1c0d3aa6 6221
c3b7224a
NC
6222 /* Detach from old frag. */
6223 if (S_GET_SEGMENT (symbolP) == bss_seg)
6224 symbol_get_frag (symbolP)->fr_symbol = NULL;
1c0d3aa6 6225
c3b7224a
NC
6226 symbol_set_frag (symbolP, frag_now);
6227 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6228 *pfrag = 0;
1c0d3aa6 6229
c3b7224a
NC
6230
6231 S_SET_SEGMENT (symbolP, bss_seg);
6232
6233#ifdef OBJ_COFF
6234 /* The symbol may already have been created with a preceding
6235 ".globl" directive -- be careful not to step on storage class
6236 in that case. Otherwise, set it to static. */
6237 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
1c0d3aa6 6238 {
c3b7224a 6239 S_SET_STORAGE_CLASS (symbolP, C_STAT);
1c0d3aa6 6240 }
c3b7224a
NC
6241#endif /* OBJ_COFF */
6242
6243#ifdef S_SET_SIZE
6244 S_SET_SIZE (symbolP, temp);
6245#endif
1c0d3aa6 6246 }
c3b7224a
NC
6247 else
6248 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
1c0d3aa6 6249
c3b7224a
NC
6250 subseg_set (current_seg, current_subseg);
6251
6252 demand_empty_rest_of_line ();
6253}
6254
6255static void
629310ab 6256s3_insert_reg (const struct s3_reg_entry *r, htab_t htab)
c3b7224a
NC
6257{
6258 int i = 0;
6259 int len = strlen (r->name) + 2;
325801bd
TS
6260 char *buf = XNEWVEC (char, len);
6261 char *buf2 = XNEWVEC (char, len);
c3b7224a
NC
6262
6263 strcpy (buf + i, r->name);
6264 for (i = 0; buf[i]; i++)
1c0d3aa6 6265 {
c3b7224a 6266 buf2[i] = TOUPPER (buf[i]);
1c0d3aa6 6267 }
c3b7224a 6268 buf2[i] = '\0';
1c0d3aa6 6269
fe0e921f
AM
6270 str_hash_insert (htab, buf, r, 0);
6271 str_hash_insert (htab, buf2, r, 0);
1c0d3aa6
NC
6272}
6273
c3b7224a
NC
6274static void
6275s3_build_reg_hsh (struct s3_reg_map *map)
1c0d3aa6 6276{
c3b7224a
NC
6277 const struct s3_reg_entry *r;
6278
f16c3d4f 6279 map->htab = str_htab_create ();
c3b7224a 6280 for (r = map->names; r->name != NULL; r++)
f16c3d4f 6281 s3_insert_reg (r, map->htab);
1c0d3aa6
NC
6282}
6283
c3b7224a 6284/* Iterate over the base tables to create the instruction patterns. */
1c0d3aa6 6285static void
c3b7224a 6286s3_build_score_ops_hsh (void)
1c0d3aa6 6287{
c3b7224a
NC
6288 unsigned int i;
6289 static struct obstack insn_obstack;
1c0d3aa6 6290
c3b7224a
NC
6291 obstack_begin (&insn_obstack, 4000);
6292 for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
6293 {
6294 const struct s3_asm_opcode *insn = s3_score_insns + i;
e57e6ddc 6295 size_t len = strlen (insn->template_name);
d3ce72d0
NC
6296 struct s3_asm_opcode *new_opcode;
6297 char *template_name;
6298 new_opcode = (struct s3_asm_opcode *)
f9e53abc 6299 obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
d3ce72d0 6300 template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
1c0d3aa6 6301
d3ce72d0
NC
6302 strcpy (template_name, insn->template_name);
6303 new_opcode->template_name = template_name;
6304 new_opcode->parms = insn->parms;
6305 new_opcode->value = insn->value;
6306 new_opcode->relax_value = insn->relax_value;
6307 new_opcode->type = insn->type;
6308 new_opcode->bitmask = insn->bitmask;
629310ab 6309 str_hash_insert (s3_score_ops_hsh, new_opcode->template_name,
fe0e921f 6310 new_opcode, 0);
c3b7224a
NC
6311 }
6312}
1c0d3aa6 6313
c3b7224a
NC
6314static void
6315s3_build_dependency_insn_hsh (void)
6316{
6317 unsigned int i;
6318 static struct obstack dependency_obstack;
1c0d3aa6 6319
c3b7224a
NC
6320 obstack_begin (&dependency_obstack, 4000);
6321 for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
6322 {
6323 const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
e57e6ddc 6324 size_t len = strlen (tmp->insn_name);
d3ce72d0 6325 struct s3_insn_to_dependency *new_i2n;
b9bb4a93 6326 char *buf;
1c0d3aa6 6327
d3ce72d0 6328 new_i2n = (struct s3_insn_to_dependency *)
f9e53abc
NC
6329 obstack_alloc (&dependency_obstack,
6330 sizeof (struct s3_insn_to_dependency));
b9bb4a93 6331 buf = (char *) obstack_alloc (&dependency_obstack, len + 1);
1c0d3aa6 6332
b9bb4a93
TS
6333 strcpy (buf, tmp->insn_name);
6334 new_i2n->insn_name = buf;
d3ce72d0 6335 new_i2n->type = tmp->type;
fe0e921f 6336 str_hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name, new_i2n, 0);
1c0d3aa6 6337 }
c3b7224a 6338}
1c0d3aa6 6339
c3b7224a
NC
6340static void
6341s_score_bss (int ignore ATTRIBUTE_UNUSED)
6342{
6343 if (score3)
6344 return s3_s_score_bss (ignore);
6345 else
6346 return s7_s_score_bss (ignore);
1c0d3aa6
NC
6347}
6348
c3b7224a
NC
6349static void
6350s_score_text (int ignore)
1c0d3aa6 6351{
c3b7224a
NC
6352 if (score3)
6353 return s3_s_score_text (ignore);
6354 else
6355 return s7_s_score_text (ignore);
6356}
6357
6358static void
6359s_section (int ignore)
6360{
6361 if (score3)
6362 return s3_score_s_section (ignore);
6363 else
6364 return s7_s_section (ignore);
6365}
1c0d3aa6 6366
c3b7224a
NC
6367static void
6368s_change_sec (int sec)
6369{
6370 if (score3)
6371 return s3_s_change_sec (sec);
1c0d3aa6 6372 else
c3b7224a
NC
6373 return s7_s_change_sec (sec);
6374}
1c0d3aa6 6375
c3b7224a
NC
6376static void
6377s_score_mask (int reg_type ATTRIBUTE_UNUSED)
6378{
6379 if (score3)
6380 return s3_s_score_mask (reg_type);
6381 else
6382 return s7_s_score_mask (reg_type);
1c0d3aa6
NC
6383}
6384
c3b7224a
NC
6385static void
6386s_score_ent (int aent)
1c0d3aa6 6387{
c3b7224a
NC
6388 if (score3)
6389 return s3_s_score_ent (aent);
6390 else
6391 return s7_s_score_ent (aent);
1c0d3aa6
NC
6392}
6393
c3b7224a
NC
6394static void
6395s_score_frame (int ignore ATTRIBUTE_UNUSED)
6396{
6397 if (score3)
6398 return s3_s_score_frame (ignore);
6399 else
6400 return s7_s_score_frame (ignore);
6401}
1c0d3aa6 6402
c3b7224a
NC
6403static void
6404s_score_end (int x ATTRIBUTE_UNUSED)
6405{
6406 if (score3)
6407 return s3_s_score_end (x);
6408 else
6409 return s7_s_score_end (x);
6410}
1c0d3aa6 6411
c3b7224a
NC
6412static void
6413s_score_set (int x ATTRIBUTE_UNUSED)
1c0d3aa6 6414{
c3b7224a
NC
6415 if (score3)
6416 return s3_s_score_set (x);
6417 else
6418 return s7_s_score_set (x);
6419}
1c0d3aa6 6420
c3b7224a
NC
6421static void
6422s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6423{
6424 if (score3)
6425 return s3_s_score_cpload (ignore);
6426 else
6427 return s7_s_score_cpload (ignore);
6428}
1c0d3aa6 6429
c3b7224a
NC
6430static void
6431s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 6432{
c3b7224a
NC
6433 if (score3)
6434 return s3_s_score_cprestore (ignore);
f9e53abc 6435 else
c3b7224a
NC
6436 return s7_s_score_cprestore (ignore);
6437}
6438
6439static void
6440s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6441{
6442 if (score3)
6443 return s3_s_score_gpword (ignore);
f9e53abc 6444 else
c3b7224a 6445 return s7_s_score_gpword (ignore);
1c0d3aa6
NC
6446}
6447
c3b7224a
NC
6448static void
6449s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 6450{
c3b7224a
NC
6451 if (score3)
6452 return s3_s_score_cpadd (ignore);
f9e53abc 6453 else
c3b7224a
NC
6454 return s7_s_score_cpadd (ignore);
6455}
1c0d3aa6 6456
c3b7224a
NC
6457static void
6458s_score_lcomm (int bytes_p)
6459{
6460 if (score3)
6461 return s3_s_score_lcomm (bytes_p);
f9e53abc 6462 else
c3b7224a 6463 return s7_s_score_lcomm (bytes_p);
1c0d3aa6
NC
6464}
6465
c3b7224a
NC
6466static void
6467s3_assemble (char *str)
6468{
6469 know (str);
6470 know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
6471
6472 memset (&s3_inst, '\0', sizeof (s3_inst));
6473 if (s3_INSN_IS_PCE_P (str))
6474 s3_parse_pce_inst (str);
6475 else if (s3_INSN_IS_48_P (str))
5b7c81bd 6476 s3_parse_48_inst (str, true);
c3b7224a 6477 else
5b7c81bd 6478 s3_parse_16_32_inst (str, true);
1c0d3aa6 6479
c3b7224a
NC
6480 if (s3_inst.error)
6481 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
6482}
1c0d3aa6 6483
1c0d3aa6 6484static void
91d6fa6a 6485s3_operand (expressionS * exp)
1c0d3aa6 6486{
c3b7224a
NC
6487 if (s3_in_my_get_expression)
6488 {
91d6fa6a 6489 exp->X_op = O_illegal;
c3b7224a
NC
6490 if (s3_inst.error == NULL)
6491 {
6492 s3_inst.error = _("bad expression");
6493 }
6494 }
1c0d3aa6
NC
6495}
6496
6497static void
c3b7224a 6498s3_begin (void)
1c0d3aa6 6499{
c3b7224a
NC
6500 unsigned int i;
6501 segT seg;
6502 subsegT subseg;
6503
f16c3d4f 6504 s3_score_ops_hsh = str_htab_create ();
c3b7224a
NC
6505
6506 s3_build_score_ops_hsh ();
6507
f16c3d4f 6508 s3_dependency_insn_hsh = str_htab_create ();
c3b7224a
NC
6509
6510 s3_build_dependency_insn_hsh ();
6511
6512 for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
6513 s3_build_reg_hsh (s3_all_reg_maps + i);
6514
6515 /* Initialize dependency vector. */
6516 s3_init_dependency_vector ();
6517
6518 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6519 seg = now_seg;
6520 subseg = now_subseg;
6521 s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
fd361982
AM
6522 bfd_set_section_flags (s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6523 bfd_set_section_alignment (s3_pdr_seg, 2);
c3b7224a
NC
6524 subseg_set (seg, subseg);
6525
6526 if (s3_USE_GLOBAL_POINTER_OPT)
6527 bfd_set_gp_size (stdoutput, s3_g_switch_value);
1c0d3aa6
NC
6528}
6529
6530static void
c3b7224a 6531s3_number_to_chars (char *buf, valueT val, int n)
1c0d3aa6 6532{
c3b7224a
NC
6533 if (target_big_endian)
6534 number_to_chars_bigendian (buf, val, n);
6535 else
6536 number_to_chars_littleendian (buf, val, n);
6537}
6538
6539static valueT
6540s3_normal_chars_to_number (char *buf, int n)
6541{
6542 valueT result = 0;
6543 unsigned char *where = (unsigned char *)buf;
6544
6545 if (target_big_endian)
6546 {
6547 while (n--)
f9e53abc 6548 {
c3b7224a 6549 result <<= 8;
f9e53abc
NC
6550 result |= (*where++ & 255);
6551 }
c3b7224a
NC
6552 }
6553 else
6554 {
6555 while (n--)
f9e53abc 6556 {
c3b7224a 6557 result <<= 8;
f9e53abc
NC
6558 result |= (where[n] & 255);
6559 }
c3b7224a 6560 }
1c0d3aa6 6561
f9e53abc 6562 return result;
1c0d3aa6
NC
6563}
6564
6565static void
c3b7224a 6566s3_number_to_chars_littleendian (void *p, valueT data, int n)
1c0d3aa6 6567{
c3b7224a 6568 char *buf = (char *) p;
1c0d3aa6 6569
c3b7224a 6570 switch (n)
1c0d3aa6 6571 {
c3b7224a
NC
6572 case 4:
6573 md_number_to_chars (buf, data >> 16, 2);
6574 md_number_to_chars (buf + 2, data, 2);
1c0d3aa6 6575 break;
c3b7224a
NC
6576 case 6:
6577 md_number_to_chars (buf, data >> 32, 2);
6578 md_number_to_chars (buf + 2, data >> 16, 2);
6579 md_number_to_chars (buf + 4, data, 2);
6580 break;
6581 default:
6582 /* Error routine. */
6583 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
1c0d3aa6
NC
6584 break;
6585 }
6586}
6587
c3b7224a
NC
6588static valueT
6589s3_chars_to_number_littleendian (const void *p, int n)
1c0d3aa6 6590{
c3b7224a
NC
6591 char *buf = (char *) p;
6592 valueT result = 0;
1c0d3aa6 6593
c3b7224a 6594 switch (n)
1c0d3aa6 6595 {
c3b7224a
NC
6596 case 4:
6597 result = s3_normal_chars_to_number (buf, 2) << 16;
6598 result |= s3_normal_chars_to_number (buf + 2, 2);
6599 break;
6600 case 6:
6601 result = s3_normal_chars_to_number (buf, 2) << 32;
6602 result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
6603 result |= s3_normal_chars_to_number (buf + 4, 2);
6604 break;
6605 default:
6606 /* Error routine. */
6607 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6608 break;
1c0d3aa6 6609 }
c3b7224a
NC
6610
6611 return result;
1c0d3aa6
NC
6612}
6613
c3b7224a
NC
6614static void
6615s3_md_number_to_chars (char *buf, valueT val, int n)
1c0d3aa6 6616{
f9e53abc 6617 if (!target_big_endian && n >= 4)
c3b7224a
NC
6618 s3_number_to_chars_littleendian (buf, val, n);
6619 else
6620 md_number_to_chars (buf, val, n);
6621}
1c0d3aa6 6622
c3b7224a
NC
6623static valueT
6624s3_md_chars_to_number (char *buf, int n)
6625{
6626 valueT result = 0;
6627
6628 if (!target_big_endian && n >= 4)
6629 result = s3_chars_to_number_littleendian (buf, n);
6630 else
6631 result = s3_normal_chars_to_number (buf, n);
6632
6633 return result;
1c0d3aa6
NC
6634}
6635
6d4af3c2 6636static const char *
c3b7224a 6637s3_atof (int type, char *litP, int *sizeP)
1c0d3aa6 6638{
c3b7224a 6639 int prec;
3076e594 6640 LITTLENUM_TYPE words[MAX_LITTLENUMS];
c3b7224a
NC
6641 char *t;
6642 int i;
1c0d3aa6 6643
c3b7224a 6644 switch (type)
1c0d3aa6 6645 {
c3b7224a
NC
6646 case 'f':
6647 case 'F':
6648 case 's':
6649 case 'S':
6650 prec = 2;
6651 break;
6652 case 'd':
6653 case 'D':
6654 case 'r':
6655 case 'R':
6656 prec = 4;
6657 break;
6658 case 'x':
6659 case 'X':
6660 case 'p':
6661 case 'P':
6662 prec = 6;
6663 break;
6664 default:
6665 *sizeP = 0;
6666 return _("bad call to MD_ATOF()");
1c0d3aa6 6667 }
c3b7224a
NC
6668
6669 t = atof_ieee (input_line_pointer, type, words);
6670 if (t)
6671 input_line_pointer = t;
6672 *sizeP = prec * 2;
6673
6674 if (target_big_endian)
1c0d3aa6 6675 {
c3b7224a 6676 for (i = 0; i < prec; i++)
1c0d3aa6 6677 {
c3b7224a
NC
6678 s3_md_number_to_chars (litP, (valueT) words[i], 2);
6679 litP += 2;
1c0d3aa6
NC
6680 }
6681 }
c3b7224a 6682 else
1c0d3aa6 6683 {
c3b7224a
NC
6684 for (i = 0; i < prec; i += 2)
6685 {
6686 s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
6687 s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
6688 litP += 4;
6689 }
1c0d3aa6 6690 }
c3b7224a
NC
6691
6692 return 0;
1c0d3aa6
NC
6693}
6694
c3b7224a
NC
6695static void
6696s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6697{
6698 know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
6699}
1c0d3aa6
NC
6700
6701static void
c3b7224a 6702s3_validate_fix (fixS *fixP)
1c0d3aa6 6703{
c3b7224a
NC
6704 fixP->fx_where += fixP->fx_frag->insn_addr;
6705}
1c0d3aa6 6706
c3b7224a
NC
6707static int
6708s3_force_relocation (struct fix *fixp)
6709{
6710 int retval = 0;
1c0d3aa6 6711
c3b7224a
NC
6712 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6713 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6714 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6715 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6716 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
f9e53abc 6717 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
c3b7224a 6718 || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
1c0d3aa6 6719 {
c3b7224a 6720 retval = 1;
1c0d3aa6 6721 }
c3b7224a 6722 return retval;
1c0d3aa6
NC
6723}
6724
5b7c81bd 6725static bool
c3b7224a 6726s3_fix_adjustable (fixS * fixP)
1c0d3aa6 6727{
c3b7224a 6728 if (fixP->fx_addsy == NULL)
1c0d3aa6 6729 {
c3b7224a 6730 return 1;
1c0d3aa6 6731 }
c3b7224a 6732 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
f9e53abc 6733 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
1c0d3aa6 6734 {
c3b7224a 6735 return 0;
1c0d3aa6 6736 }
c3b7224a
NC
6737 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6738 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6739 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6740 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
1c0d3aa6 6741 {
c3b7224a 6742 return 0;
1c0d3aa6 6743 }
1c0d3aa6 6744
c3b7224a 6745 return 1;
1c0d3aa6
NC
6746}
6747
1c0d3aa6 6748static void
c3b7224a 6749s3_elf_final_processing (void)
1c0d3aa6 6750{
c3b7224a 6751 unsigned long val = 0;
1c0d3aa6 6752
c3b7224a
NC
6753 if (score3)
6754 val = E_SCORE_MACH_SCORE3;
6755 else if (score7)
6756 val = E_SCORE_MACH_SCORE7;
1c0d3aa6 6757
c3b7224a
NC
6758 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6759 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6760 elf_elfheader (stdoutput)->e_flags |= val;
1c0d3aa6 6761
c3b7224a 6762 if (s3_fix_data_dependency == 1)
1c0d3aa6 6763 {
c3b7224a 6764 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
1c0d3aa6 6765 }
c3b7224a 6766 if (s3_score_pic == s3_PIC)
1c0d3aa6 6767 {
c3b7224a 6768 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
1c0d3aa6 6769 }
c3b7224a 6770}
1c0d3aa6 6771
c3b7224a
NC
6772static int
6773s3_judge_size_before_relax (fragS * fragp, asection *sec)
6774{
6775 int change = 0;
1c0d3aa6 6776
c3b7224a
NC
6777 if (s3_score_pic == s3_NO_PIC)
6778 change = s3_nopic_need_relax (fragp->fr_symbol, 0);
1c0d3aa6 6779 else
c3b7224a 6780 change = s3_pic_need_relax (fragp->fr_symbol, sec);
1c0d3aa6 6781
c3b7224a
NC
6782 if (change == 1)
6783 {
6784 /* Only at the first time determining whether s3_GP instruction relax should be done,
33eaf5de 6785 return the difference between instruction size and instruction relax size. */
c3b7224a
NC
6786 if (fragp->fr_opcode == NULL)
6787 {
6788 fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
6789 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6790 return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
6791 }
1c0d3aa6 6792 }
c3b7224a
NC
6793
6794 return 0;
1c0d3aa6
NC
6795}
6796
c3b7224a
NC
6797static int
6798s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
1c0d3aa6 6799{
c3b7224a
NC
6800 if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6801 || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6802 return s3_judge_size_before_relax (fragp, sec);
1c0d3aa6 6803
c3b7224a
NC
6804 return 0;
6805}
1c0d3aa6 6806
c3b7224a
NC
6807static int
6808s3_relax_branch_inst32 (fragS * fragp)
6809{
6810 fragp->fr_opcode = NULL;
6811 return 0;
6812}
1c0d3aa6 6813
c3b7224a
NC
6814static int
6815s3_relax_branch_inst16 (fragS * fragp)
6816{
6817 int relaxable_p = 0;
6818 int frag_addr = fragp->fr_address + fragp->insn_addr;
6819 addressT symbol_address = 0;
6820 symbolS *s;
6821 offsetT offset;
6822 long value;
6823 unsigned long inst_value;
6824
6825 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6826
6827 s = fragp->fr_symbol;
6828 if (s == NULL)
6829 frag_addr = 0;
6830 else
8d1015a8 6831 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
c3b7224a
NC
6832
6833 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
6834 offset = (inst_value & 0x1ff) << 1;
6835 if ((offset & 0x200) == 0x200)
6836 offset |= 0xfffffc00;
6837
6838 value = offset + symbol_address - frag_addr;
6839
f9e53abc 6840 if (relaxable_p
c3b7224a
NC
6841 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6842 && fragp->fr_fix == 2
c3b7224a
NC
6843 && (S_IS_DEFINED (s)
6844 && !S_IS_COMMON (s)
6845 && !S_IS_EXTERNAL (s)))
1c0d3aa6 6846 {
c3b7224a
NC
6847 /* Relax branch 32 to branch 16. */
6848 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6849 fragp->fr_fix = 4;
6850 return 2;
1c0d3aa6 6851 }
c3b7224a
NC
6852 else
6853 return 0;
6854}
6855
6856static int
6857s3_relax_cmpbranch_inst32 (fragS * fragp)
6858{
6859 int relaxable_p = 0;
6860 symbolS *s;
6861 /* For sign bit. */
6862 long offset;
6863 long frag_addr = fragp->fr_address + fragp->insn_addr;
6864 long symbol_address = 0;
6865 long value;
6866 unsigned long inst_value;
6867
6868 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6869
6870 s = fragp->fr_symbol;
6871 if (s == NULL)
6872 frag_addr = 0;
6873 else
8d1015a8 6874 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
c3b7224a
NC
6875
6876 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
6877 offset = (inst_value & 0x1)
f9e53abc
NC
6878 | (((inst_value >> 7) & 0x7) << 1)
6879 | (((inst_value >> 21) & 0x1f) << 4);
c3b7224a
NC
6880 offset <<= 1;
6881 if ((offset & 0x200) == 0x200)
6882 offset |= 0xfffffe00;
6883
6884 value = offset + symbol_address - frag_addr;
6885 /* change the order of judging rule is because
33eaf5de 6886 1.not defined symbol or common symbol or external symbol will change
f9e53abc
NC
6887 bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
6888 2.if the flow is as before : it will results to recursive loop
c3b7224a
NC
6889 */
6890 if (fragp->fr_fix == 6)
f9e53abc 6891 {
c3b7224a
NC
6892 /* Have already relaxed! Just return 0 to terminate the loop. */
6893 return 0;
1c0d3aa6 6894 }
33eaf5de 6895 /* need to translate when extern or not defined or common symbol */
f9e53abc
NC
6896 else if ((relaxable_p
6897 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
8d1015a8 6898 && fragp->fr_fix == 4)
f9e53abc
NC
6899 || !S_IS_DEFINED (s)
6900 ||S_IS_COMMON (s)
6901 ||S_IS_EXTERNAL (s))
1c0d3aa6 6902 {
c3b7224a
NC
6903 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6904 fragp->fr_fix = 6;
6905 return 2;
1c0d3aa6
NC
6906 }
6907 else
f9e53abc 6908 {
c3b7224a
NC
6909 /* Never relax. Modify fr_opcode to NULL to verify it's value in
6910 md_apply_fix. */
6911 fragp->fr_opcode = NULL;
6912 return 0;
1c0d3aa6
NC
6913 }
6914}
6915
1c0d3aa6 6916
c3b7224a
NC
6917static int
6918s3_relax_other_inst32 (fragS * fragp)
1c0d3aa6 6919{
c3b7224a 6920 int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
1c0d3aa6 6921
c3b7224a
NC
6922 if (relaxable_p
6923 && fragp->fr_fix == 4)
1c0d3aa6 6924 {
c3b7224a
NC
6925 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6926 fragp->fr_fix = 2;
6927 return -2;
1c0d3aa6 6928 }
c3b7224a
NC
6929 else
6930 return 0;
6931}
1c0d3aa6 6932
c3b7224a
NC
6933static int
6934s3_relax_gp_and_pic_inst32 (void)
6935{
f9e53abc 6936 /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
c3b7224a
NC
6937 instructions. We don't change relax size here. */
6938 return 0;
6939}
1c0d3aa6 6940
c3b7224a
NC
6941static int
6942s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
6943{
6944 int grows = 0;
6945 int adjust_align_p = 0;
1c0d3aa6 6946
c3b7224a
NC
6947 /* If the instruction address is odd, make it half word align first. */
6948 if ((fragp->fr_address) % 2 != 0)
6949 {
6950 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
f9e53abc 6951 {
c3b7224a
NC
6952 fragp->insn_addr = 1;
6953 grows += 1;
6954 adjust_align_p = 1;
f9e53abc 6955 }
c3b7224a 6956 }
1c0d3aa6 6957
c3b7224a
NC
6958 switch (s3_RELAX_TYPE (fragp->fr_subtype))
6959 {
6960 case PC_DISP19div2:
6961 grows += s3_relax_branch_inst32 (fragp);
6962 break;
1c0d3aa6 6963
c3b7224a
NC
6964 case PC_DISP8div2:
6965 grows += s3_relax_branch_inst16 (fragp);
6966 break;
1c0d3aa6 6967
c3b7224a
NC
6968 case Insn_BCMP :
6969 grows += s3_relax_cmpbranch_inst32 (fragp);
6970 break;
1c0d3aa6 6971
c3b7224a
NC
6972 case Insn_GP:
6973 case Insn_PIC:
6974 grows += s3_relax_gp_and_pic_inst32 ();
6975 break;
1c0d3aa6 6976
c3b7224a
NC
6977 default:
6978 grows += s3_relax_other_inst32 (fragp);
6979 break;
1c0d3aa6
NC
6980 }
6981
c3b7224a
NC
6982 /* newly added */
6983 if (adjust_align_p && fragp->insn_addr)
8fce5f8c 6984 {
c3b7224a 6985 fragp->fr_fix += fragp->insn_addr;
8fce5f8c
ML
6986 }
6987
c3b7224a
NC
6988 return grows;
6989}
6990
6991static void
6992s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
6993{
90bd3c90
AM
6994 unsigned int r_old;
6995 unsigned int r_new;
c3b7224a
NC
6996 char backup[20];
6997 fixS *fixp;
6998
d3ce72d0
NC
6999 r_old = s3_RELAX_OLD (fragp->fr_subtype);
7000 r_new = s3_RELAX_NEW (fragp->fr_subtype);
1c0d3aa6 7001
c3b7224a
NC
7002 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
7003 if (fragp->fr_opcode == NULL)
8fce5f8c 7004 {
d3ce72d0
NC
7005 memcpy (backup, fragp->fr_literal, r_old);
7006 fragp->fr_fix = r_old;
8fce5f8c
ML
7007 }
7008 else
7009 {
d3ce72d0
NC
7010 memcpy (backup, fragp->fr_literal + r_old, r_new);
7011 fragp->fr_fix = r_new;
c3b7224a 7012 }
8fce5f8c 7013
c3b7224a 7014 fixp = fragp->tc_frag_data.fixp;
d3ce72d0 7015 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
c3b7224a
NC
7016 {
7017 if (fragp->fr_opcode)
7018 fixp->fx_done = 1;
7019 fixp = fixp->fx_next;
7020 }
7021 while (fixp && fixp->fx_frag == fragp)
7022 {
7023 if (fragp->fr_opcode)
d3ce72d0 7024 fixp->fx_where -= r_old + fragp->insn_addr;
c3b7224a
NC
7025 else
7026 fixp->fx_done = 1;
7027 fixp = fixp->fx_next;
8fce5f8c
ML
7028 }
7029
c3b7224a
NC
7030 if (fragp->insn_addr)
7031 {
7032 s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
7033 }
7034 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
7035 fragp->fr_fix += fragp->insn_addr;
1c0d3aa6
NC
7036}
7037
c3b7224a
NC
7038static long
7039s3_pcrel_from (fixS * fixP)
1c0d3aa6 7040{
c3b7224a 7041 long retval = 0;
1c0d3aa6 7042
c3b7224a
NC
7043 if (fixP->fx_addsy
7044 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
7045 && (fixP->fx_subsy == NULL))
1c0d3aa6 7046 {
c3b7224a 7047 retval = 0;
1c0d3aa6 7048 }
c3b7224a 7049 else
1c0d3aa6 7050 {
c3b7224a 7051 retval = fixP->fx_where + fixP->fx_frag->fr_address;
1c0d3aa6 7052 }
c3b7224a
NC
7053
7054 return retval;
1c0d3aa6
NC
7055}
7056
c3b7224a
NC
7057static valueT
7058s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7059{
fd361982 7060 int align = bfd_section_alignment (segment);
8d3842cd 7061 return ((size + (1 << align) - 1) & -(1 << align));
c3b7224a 7062}
1c0d3aa6
NC
7063
7064static void
c3b7224a 7065s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
1c0d3aa6 7066{
548c8b2b
AM
7067 valueT value = *valP;
7068 valueT newval;
7069 valueT content;
7070 valueT HI, LO;
1c0d3aa6 7071
c3b7224a
NC
7072 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
7073
9c2799c2 7074 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
c3b7224a 7075 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
1c0d3aa6 7076 {
c3b7224a
NC
7077 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
7078 fixP->fx_done = 1;
1c0d3aa6
NC
7079 }
7080
c3b7224a
NC
7081 /* If this symbol is in a different section then we need to leave it for
7082 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
7083 so we have to undo it's effects here. */
7084 if (fixP->fx_pcrel)
1c0d3aa6 7085 {
c3b7224a
NC
7086 if (fixP->fx_addsy != NULL
7087 && S_IS_DEFINED (fixP->fx_addsy)
7088 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7089 value += md_pcrel_from (fixP);
1c0d3aa6 7090 }
1c0d3aa6 7091
c3b7224a
NC
7092 /* Remember value for emit_reloc. */
7093 fixP->fx_addnumber = value;
1c0d3aa6 7094
c3b7224a
NC
7095 switch (fixP->fx_r_type)
7096 {
7097 case BFD_RELOC_HI16_S:
7098 if (fixP->fx_done) /* For la rd, imm32. */
7099 {
7100 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
548c8b2b 7101 HI = value >> 16; /* mul to 2, then take the hi 16 bit. */
c3b7224a
NC
7102 newval |= (HI & 0x3fff) << 1;
7103 newval |= ((HI >> 14) & 0x3) << 16;
7104 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7105 }
7106 break;
7107 case BFD_RELOC_LO16:
7108 if (fixP->fx_done) /* For la rd, imm32. */
7109 {
7110 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
548c8b2b 7111 LO = value & 0xffff;
c3b7224a
NC
7112 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
7113 newval |= ((LO >> 14) & 0x3) << 16;
7114 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7115 }
7116 break;
7117 case BFD_RELOC_SCORE_JMP:
7118 {
7119 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7120 value = fixP->fx_offset;
7121 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
7122 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7123 }
7124 break;
1c0d3aa6 7125
c3b7224a
NC
7126 case BFD_RELOC_SCORE_IMM30:
7127 {
7128 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7129 value = fixP->fx_offset;
7130 value >>= 2;
7131 content = (content & ~0x7f7fff7f80LL)
f9e53abc
NC
7132 | (((value & 0xff) >> 0) << 7)
7133 | (((value & 0x7fff00) >> 8) << 16)
7134 | (((value & 0x3f800000) >> 23) << 32);
c3b7224a
NC
7135 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7136 break;
7137 }
1c0d3aa6 7138
c3b7224a
NC
7139 case BFD_RELOC_SCORE_IMM32:
7140 {
7141 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7142 value = fixP->fx_offset;
7143 content = (content & ~0x7f7fff7fe0LL)
f9e53abc
NC
7144 | ((value & 0x3ff) << 5)
7145 | (((value >> 10) & 0x7fff) << 16)
7146 | (((value >> 25) & 0x7f) << 32);
c3b7224a
NC
7147 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7148 break;
7149 }
1c0d3aa6 7150
c3b7224a
NC
7151 case BFD_RELOC_SCORE_BRANCH:
7152 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7153 value = fixP->fx_offset;
7154 else
7155 fixP->fx_done = 1;
7156
7157 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7158
7159 /* Don't check c-bit. */
7160 if (fixP->fx_frag->fr_opcode != 0)
7161 {
7162 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7163 {
7164 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7165 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7166 return;
7167 }
7168 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7169 content &= 0xfe00;
7170 content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7171 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7172 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
7173 fixP->fx_size = 2;
7174 }
7175 else
7176 {
7177 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7178 {
7179 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7180 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7181 return;
7182 }
7183 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7184 content &= 0xfc00fc01;
7185 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7186 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7187 }
7188 break;
7189 case BFD_RELOC_SCORE16_JMP:
7190 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7191 content &= 0xf001;
7192 value = fixP->fx_offset & 0xfff;
7193 content = (content & 0xfc01) | (value & 0xffe);
7194 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7195 break;
f9e53abc 7196 case BFD_RELOC_SCORE16_BRANCH:
c3b7224a
NC
7197 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7198 /* Don't check c-bit. */
7199 if (fixP->fx_frag->fr_opcode != 0)
7200 {
7201 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7202 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7203 value = fixP->fx_offset;
7204 else
7205 fixP->fx_done = 1;
7206 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7207 {
7208 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7209 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7210 return;
7211 }
7212 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7213 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7214 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7215 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7216 fixP->fx_size = 4;
7217 break;
7218 }
7219 else
7220 {
2b0f3761 7221 /* In different section. */
c3b7224a
NC
7222 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7223 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7224 value = fixP->fx_offset;
7225 else
7226 fixP->fx_done = 1;
7227
7228 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7229 {
7230 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7231 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7232 return;
7233 }
7234
7235 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7236 content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7237 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7238 break;
7239 }
7240
f9e53abc 7241 break;
c3b7224a
NC
7242
7243 case BFD_RELOC_SCORE_BCMP:
7244 if (fixP->fx_frag->fr_opcode != 0)
7245 {
7246 char *buf_ptr = buf;
7247 buf_ptr += 2;
7248
7249 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7250 value = fixP->fx_offset;
7251 else
7252 fixP->fx_done = 1;
7253
f9e53abc 7254 /* NOTE!!!
c3b7224a
NC
7255 bcmp -> cmp! and branch, so value -= 2. */
7256 value -= 2;
7257
7258 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7259 {
7260 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7261 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7262 return;
7263 }
7264
7265 content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
7266 content &= 0xfc00fc01;
7267 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7268 s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
7269 /* change relocation type to BFD_RELOC_SCORE_BRANCH */
7270 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7271 fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
7272 break;
7273 }
7274 else
7275 {
7276 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7277 value = fixP->fx_offset;
7278 else
7279 fixP->fx_done = 1;
1c0d3aa6 7280
c3b7224a 7281 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
1c0d3aa6 7282
c3b7224a
NC
7283 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7284 {
7285 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7286 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7287 return;
7288 }
1c0d3aa6 7289
c3b7224a
NC
7290 value >>= 1;
7291 content &= ~0x03e00381;
7292 content = content
f9e53abc
NC
7293 | (value & 0x1)
7294 | (((value & 0xe) >> 1) << 7)
7295 | (((value & 0x1f0) >> 4) << 21);
1c0d3aa6 7296
c3b7224a
NC
7297 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7298 break;
7299 }
1c0d3aa6 7300
c3b7224a
NC
7301 case BFD_RELOC_8:
7302 if (fixP->fx_done || fixP->fx_pcrel)
7303 s3_md_number_to_chars (buf, value, 1);
7304#ifdef OBJ_ELF
7305 else
1c0d3aa6 7306 {
c3b7224a
NC
7307 value = fixP->fx_offset;
7308 s3_md_number_to_chars (buf, value, 1);
1c0d3aa6 7309 }
1c0d3aa6 7310#endif
c3b7224a 7311 break;
1c0d3aa6 7312
c3b7224a
NC
7313 case BFD_RELOC_16:
7314 if (fixP->fx_done || fixP->fx_pcrel)
7315 s3_md_number_to_chars (buf, value, 2);
7316#ifdef OBJ_ELF
7317 else
1c0d3aa6 7318 {
c3b7224a
NC
7319 value = fixP->fx_offset;
7320 s3_md_number_to_chars (buf, value, 2);
1c0d3aa6 7321 }
c3b7224a
NC
7322#endif
7323 break;
7324 case BFD_RELOC_RVA:
7325 case BFD_RELOC_32:
7326 if (fixP->fx_done || fixP->fx_pcrel)
7327 md_number_to_chars (buf, value, 4);
7328#ifdef OBJ_ELF
1c0d3aa6
NC
7329 else
7330 {
c3b7224a
NC
7331 value = fixP->fx_offset;
7332 md_number_to_chars (buf, value, 4);
1c0d3aa6 7333 }
c3b7224a
NC
7334#endif
7335 break;
7336 case BFD_RELOC_VTABLE_INHERIT:
7337 fixP->fx_done = 0;
7338 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
7339 S_SET_WEAK (fixP->fx_addsy);
7340 break;
7341 case BFD_RELOC_VTABLE_ENTRY:
7342 fixP->fx_done = 0;
7343 break;
7344 case BFD_RELOC_SCORE_GPREL15:
7345 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7346 /* c-bit. */
7347 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
7348 fixP->fx_r_type = BFD_RELOC_NONE;
7349 fixP->fx_done = 0;
7350 break;
7351 case BFD_RELOC_SCORE_GOT15:
7352 case BFD_RELOC_SCORE_DUMMY_HI16:
7353 case BFD_RELOC_SCORE_GOT_LO16:
7354 case BFD_RELOC_SCORE_CALL15:
7355 case BFD_RELOC_GPREL32:
7356 break;
7357 case BFD_RELOC_NONE:
7358 default:
7359 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
1c0d3aa6 7360 }
c3b7224a 7361}
1c0d3aa6 7362
c3b7224a
NC
7363static arelent **
7364s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7365{
7366 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
7367 arelent *reloc;
7368 bfd_reloc_code_real_type code;
585ba040 7369 const char *type;
1c0d3aa6 7370
325801bd 7371 reloc = retval[0] = XNEW (arelent);
c3b7224a 7372 retval[1] = NULL;
1c0d3aa6 7373
325801bd 7374 reloc->sym_ptr_ptr = XNEW (asymbol *);
c3b7224a
NC
7375 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7376 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7377 reloc->addend = fixp->fx_offset;
7378
7379 /* If this is a variant frag, we may need to adjust the existing
7380 reloc and generate a new one. */
7381 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
1c0d3aa6 7382 {
c3b7224a
NC
7383 /* Update instruction imm bit. */
7384 offsetT newval;
7385 unsigned short off;
7386 char *buf;
1c0d3aa6 7387
c3b7224a
NC
7388 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
7389 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7390 off = fixp->fx_offset >> 16;
7391 newval |= (off & 0x3fff) << 1;
7392 newval |= ((off >> 14) & 0x3) << 16;
7393 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
1c0d3aa6 7394
c3b7224a
NC
7395 buf += s3_INSN_SIZE;
7396 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7397 off = fixp->fx_offset & 0xffff;
7398 newval |= ((off & 0x3fff) << 1);
7399 newval |= (((off >> 14) & 0x3) << 16);
7400 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
1c0d3aa6 7401
325801bd 7402 retval[1] = XNEW (arelent);
c3b7224a 7403 retval[2] = NULL;
325801bd 7404 retval[1]->sym_ptr_ptr = XNEW (asymbol *);
c3b7224a
NC
7405 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7406 retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
7407
c3b7224a
NC
7408 retval[1]->addend = 0;
7409 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
9c2799c2 7410 gas_assert (retval[1]->howto != NULL);
c3b7224a
NC
7411
7412 fixp->fx_r_type = BFD_RELOC_HI16_S;
1c0d3aa6 7413 }
c3b7224a
NC
7414
7415 code = fixp->fx_r_type;
7416 switch (fixp->fx_r_type)
1c0d3aa6 7417 {
c3b7224a
NC
7418 case BFD_RELOC_32:
7419 if (fixp->fx_pcrel)
1c0d3aa6 7420 {
c3b7224a
NC
7421 code = BFD_RELOC_32_PCREL;
7422 break;
1c0d3aa6 7423 }
1a0670f3 7424 /* Fall through. */
c3b7224a
NC
7425 case BFD_RELOC_HI16_S:
7426 case BFD_RELOC_LO16:
7427 case BFD_RELOC_SCORE_JMP:
7428 case BFD_RELOC_SCORE_BRANCH:
7429 case BFD_RELOC_SCORE16_JMP:
7430 case BFD_RELOC_SCORE16_BRANCH:
7431 case BFD_RELOC_SCORE_BCMP:
7432 case BFD_RELOC_VTABLE_ENTRY:
7433 case BFD_RELOC_VTABLE_INHERIT:
7434 case BFD_RELOC_SCORE_GPREL15:
7435 case BFD_RELOC_SCORE_GOT15:
7436 case BFD_RELOC_SCORE_DUMMY_HI16:
7437 case BFD_RELOC_SCORE_GOT_LO16:
7438 case BFD_RELOC_SCORE_CALL15:
7439 case BFD_RELOC_GPREL32:
7440 case BFD_RELOC_NONE:
7441 case BFD_RELOC_SCORE_IMM30:
7442 case BFD_RELOC_SCORE_IMM32:
7443 code = fixp->fx_r_type;
7444 break;
7445 default:
7446 type = _("<unknown>");
7447 as_bad_where (fixp->fx_file, fixp->fx_line,
7448 _("cannot represent %s relocation in this object file format"), type);
7449 return NULL;
1c0d3aa6
NC
7450 }
7451
c3b7224a
NC
7452 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7453 if (reloc->howto == NULL)
1c0d3aa6 7454 {
c3b7224a
NC
7455 as_bad_where (fixp->fx_file, fixp->fx_line,
7456 _("cannot represent %s relocation in this object file format1"),
7457 bfd_get_reloc_code_name (code));
7458 return NULL;
7459 }
7460 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
7461 vtable entry to be used in the relocation's section offset. */
7462 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
7463 reloc->address = fixp->fx_offset;
7464
7465 return retval;
7466}
7467
7468void
7469md_assemble (char *str)
7470{
7471 if (score3)
7472 s3_assemble (str);
7473 else
7474 s7_assemble (str);
7475}
7476
7477/* We handle all bad expressions here, so that we can report the faulty
7478 instruction in the error message. */
7479void
91d6fa6a 7480md_operand (expressionS * exp)
c3b7224a
NC
7481{
7482 if (score3)
91d6fa6a 7483 s3_operand (exp);
c3b7224a 7484 else
91d6fa6a 7485 s7_operand (exp);
c3b7224a
NC
7486}
7487
7488/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7489 for use in the a.out file, and stores them in the array pointed to by buf.
7490 This knows about the endian-ness of the target machine and does
7491 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7492 2 (short) and 4 (long) Floating numbers are put out as a series of
7493 LITTLENUMS (shorts, here at least). */
7494void
7495md_number_to_chars (char *buf, valueT val, int n)
7496{
7497 if (score3)
7498 s3_number_to_chars (buf, val, n);
7499 else
7500 s7_number_to_chars (buf, val, n);
7501}
1c0d3aa6 7502
c3b7224a
NC
7503/* Turn a string in input_line_pointer into a floating point constant
7504 of type TYPE, and store the appropriate bytes in *LITP. The number
7505 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7506 returned, or NULL on OK.
7507
7508 Note that fp constants aren't represent in the normal way on the ARM.
7509 In big endian mode, things are as expected. However, in little endian
7510 mode fp constants are big-endian word-wise, and little-endian byte-wise
7511 within the words. For example, (double) 1.1 in big endian mode is
7512 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7513 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6d4af3c2 7514const char *
c3b7224a
NC
7515md_atof (int type, char *litP, int *sizeP)
7516{
7517 if (score3)
7518 return s3_atof (type, litP, sizeP);
7519 else
7520 return s7_atof (type, litP, sizeP);
7521}
1c0d3aa6 7522
c3b7224a
NC
7523void
7524score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
7525{
7526 if (score3)
7527 s3_frag_check (fragp);
7528 else
7529 s7_frag_check (fragp);
7530}
1c0d3aa6 7531
c3b7224a
NC
7532/* Implementation of TC_VALIDATE_FIX.
7533 Called before md_apply_fix() and after md_convert_frag(). */
7534void
7535score_validate_fix (fixS *fixP)
7536{
7537 if (score3)
7538 s3_validate_fix (fixP);
7539 else
7540 s7_validate_fix (fixP);
7541}
1c0d3aa6 7542
c3b7224a
NC
7543int
7544score_force_relocation (struct fix *fixp)
7545{
7546 if (score3)
7547 return s3_force_relocation (fixp);
7548 else
7549 return s7_force_relocation (fixp);
7550}
1c0d3aa6 7551
c3b7224a
NC
7552/* Implementation of md_frag_check.
7553 Called after md_convert_frag(). */
5b7c81bd 7554bool
c3b7224a
NC
7555score_fix_adjustable (fixS * fixP)
7556{
7557 if (score3)
7558 return s3_fix_adjustable (fixP);
7559 else
7560 return s7_fix_adjustable (fixP);
7561}
1c0d3aa6 7562
c3b7224a
NC
7563void
7564score_elf_final_processing (void)
7565{
7566 if (score3)
7567 s3_elf_final_processing ();
7568 else
7569 s7_elf_final_processing ();
7570}
1c0d3aa6 7571
c3b7224a
NC
7572/* In this function, we determine whether s3_GP instruction should do relaxation,
7573 for the label being against was known now.
7574 Doing this here but not in md_relax_frag() can induce iteration times
7575 in stage of doing relax. */
7576int
7577md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
7578{
7579 if (score3)
7580 return s3_estimate_size_before_relax (fragp, sec);
7581 else
7582 return s7_estimate_size_before_relax (fragp, sec);
7583}
1c0d3aa6 7584
c3b7224a
NC
7585int
7586score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
7587{
7588 if (score3)
7589 return s3_relax_frag (sec, fragp, stretch);
f9e53abc 7590 else
c3b7224a
NC
7591 return s7_relax_frag (sec, fragp, stretch);
7592}
7593
7594void
7595md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7596{
7597 if (score3)
7598 return s3_convert_frag (abfd, sec, fragp);
1c0d3aa6 7599 else
c3b7224a
NC
7600 return s7_convert_frag (abfd, sec, fragp);
7601}
1c0d3aa6 7602
c3b7224a
NC
7603long
7604md_pcrel_from (fixS * fixP)
7605{
7606 if (score3)
7607 return s3_pcrel_from (fixP);
7608 else
7609 return s7_pcrel_from (fixP);
7610}
1c0d3aa6 7611
c3b7224a
NC
7612/* Round up a section size to the appropriate boundary. */
7613valueT
7614md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7615{
7616 if (score3)
7617 return s3_section_align (segment, size);
7618 else
7619 return s7_section_align (segment, size);
1c0d3aa6
NC
7620}
7621
c3b7224a
NC
7622void
7623md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1c0d3aa6 7624{
c3b7224a
NC
7625 if (score3)
7626 return s3_apply_fix (fixP, valP, seg);
7627 else
7628 return s7_apply_fix (fixP, valP, seg);
7629}
1c0d3aa6 7630
c3b7224a
NC
7631/* Translate internal representation of relocation info to BFD target format. */
7632arelent **
7633tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7634{
7635 if (score3)
7636 return s3_gen_reloc (section, fixp);
7637 else
7638 return s7_gen_reloc (section, fixp);
7639}
1c0d3aa6 7640
c3b7224a
NC
7641void
7642md_begin (void)
7643{
7644 s3_begin ();
7645 s7_begin ();
1c0d3aa6
NC
7646}
7647
7648static void
c3b7224a 7649score_set_mach (const char *arg)
1c0d3aa6 7650{
c3b7224a 7651 if (strcmp (arg, MARCH_SCORE3) == 0)
1c0d3aa6 7652 {
c3b7224a
NC
7653 score3 = 1;
7654 score7 = 0;
7655 s3_score3d = 1;
1c0d3aa6 7656 }
c3b7224a
NC
7657 else if (strcmp (arg, MARCH_SCORE7) == 0)
7658 {
7659 score3 = 0;
7660 score7 = 1;
7661 s7_score7d = 1;
7662 s7_university_version = 0;
7663 s7_vector_size = s7_SCORE7_PIPELINE;
7664 }
7665 else if (strcmp (arg, MARCH_SCORE5) == 0)
7666 {
7667 score3 = 0;
7668 score7 = 1;
7669 s7_score7d = 1;
7670 s7_university_version = 0;
7671 s7_vector_size = s7_SCORE5_PIPELINE;
7672 }
7673 else if (strcmp (arg, MARCH_SCORE5U) == 0)
7674 {
7675 score3 = 0;
7676 score7 = 1;
7677 s7_score7d = 1;
7678 s7_university_version = 1;
7679 s7_vector_size = s7_SCORE5_PIPELINE;
7680 }
7681 else
1c0d3aa6 7682 {
c3b7224a 7683 as_bad (_("unknown architecture `%s'\n"), arg);
1c0d3aa6
NC
7684 }
7685}
7686
c3b7224a 7687int
17b9d67d 7688md_parse_option (int c, const char *arg)
1c0d3aa6 7689{
c3b7224a
NC
7690 switch (c)
7691 {
7692#ifdef OPTION_EB
7693 case OPTION_EB:
7694 target_big_endian = 1;
7695 break;
7696#endif
7697#ifdef OPTION_EL
7698 case OPTION_EL:
7699 target_big_endian = 0;
7700 break;
7701#endif
7702 case OPTION_FIXDD:
7703 s3_fix_data_dependency = 1;
7704 s7_fix_data_dependency = 1;
7705 break;
7706 case OPTION_NWARN:
7707 s3_warn_fix_data_dependency = 0;
7708 s7_warn_fix_data_dependency = 0;
7709 break;
7710 case OPTION_SCORE5:
7711 score3 = 0;
7712 score7 = 1;
7713 s7_university_version = 0;
7714 s7_vector_size = s7_SCORE5_PIPELINE;
7715 break;
7716 case OPTION_SCORE5U:
7717 score3 = 0;
7718 score7 = 1;
7719 s7_university_version = 1;
7720 s7_vector_size = s7_SCORE5_PIPELINE;
7721 break;
7722 case OPTION_SCORE7:
7723 score3 = 0;
7724 score7 = 1;
7725 s7_score7d = 1;
7726 s7_university_version = 0;
7727 s7_vector_size = s7_SCORE7_PIPELINE;
7728 break;
7729 case OPTION_SCORE3:
7730 score3 = 1;
7731 score7 = 0;
7732 s3_score3d = 1;
7733 break;
7734 case OPTION_R1:
7735 s3_nor1 = 0;
7736 s7_nor1 = 0;
7737 break;
7738 case 'G':
7739 s3_g_switch_value = atoi (arg);
7740 s7_g_switch_value = atoi (arg);
7741 break;
7742 case OPTION_O0:
7743 s3_g_opt = 0;
7744 s7_g_opt = 0;
7745 break;
7746 case OPTION_SCORE_VERSION:
7747 printf (_("Sunplus-v2-0-0-20060510\n"));
7748 break;
7749 case OPTION_PIC:
7750 s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */
7751 s7_score_pic = s7_PIC;
7752 s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */
7753 s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */
7754 break;
7755 case OPTION_MARCH:
7756 score_set_mach (arg);
7757 break;
7758 default:
7759 return 0;
7760 }
7761 return 1;
1c0d3aa6
NC
7762}
7763
c3b7224a
NC
7764void
7765md_show_usage (FILE * fp)
1c0d3aa6 7766{
c3b7224a
NC
7767 fprintf (fp, _(" Score-specific assembler options:\n"));
7768#ifdef OPTION_EB
7769 fprintf (fp, _("\
7770 -EB\t\tassemble code for a big-endian cpu\n"));
7771#endif
7772
7773#ifdef OPTION_EL
7774 fprintf (fp, _("\
7775 -EL\t\tassemble code for a little-endian cpu\n"));
7776#endif
1c0d3aa6 7777
c3b7224a 7778 fprintf (fp, _("\
33eaf5de 7779 -FIXDD\t\tfix data dependencies\n"));
c3b7224a 7780 fprintf (fp, _("\
33eaf5de 7781 -NWARN\t\tdo not print warning message when fixing data dependencies\n"));
c3b7224a 7782 fprintf (fp, _("\
33eaf5de 7783 -SCORE5\t\tassemble code for target SCORE5\n"));
c3b7224a 7784 fprintf (fp, _("\
33eaf5de 7785 -SCORE5U\tassemble code for target SCORE5U\n"));
c3b7224a 7786 fprintf (fp, _("\
33eaf5de 7787 -SCORE7\t\tassemble code for target SCORE7 [default]\n"));
c3b7224a 7788 fprintf (fp, _("\
33eaf5de 7789 -SCORE3\t\tassemble code for target SCORE3\n"));
c3b7224a 7790 fprintf (fp, _("\
33eaf5de 7791 -march=score7\tassemble code for target SCORE7 [default]\n"));
c3b7224a 7792 fprintf (fp, _("\
33eaf5de 7793 -march=score3\tassemble code for target SCORE3\n"));
c3b7224a
NC
7794 fprintf (fp, _("\
7795 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
7796 fprintf (fp, _("\
33eaf5de 7797 -KPIC\t\tgenerate PIC\n"));
c3b7224a 7798 fprintf (fp, _("\
33eaf5de 7799 -O0\t\tdo not perform any optimizations\n"));
c3b7224a 7800 fprintf (fp, _("\
33eaf5de 7801 -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n"));
c3b7224a 7802 fprintf (fp, _("\
33eaf5de 7803 -V \t\tSunplus release version\n"));
c3b7224a 7804}