tc-score.c: Replace overlapping sprintf with memmove
[deliverable/binutils-gdb.git] / gas / config / tc-score.c
CommitLineData
1c0d3aa6 1/* tc-score.c -- Assembler for Score
b3adc24a 2 Copyright (C) 2006-2020 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);
68static bfd_boolean s3_fix_adjustable (fixS * fixP);
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
NC
461 int max_regno;
462 struct hash_control *htab;
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
c3b7224a
NC
473static struct hash_control *s3_score_ops_hsh = NULL;
474static struct hash_control *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
c3b7224a 1030s3_score_reg_parse (char **ccp, struct hash_control *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;
c3b7224a 1047 reg = (struct s3_reg_entry *) 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);
c3b7224a 2206 tmp = (const struct s3_insn_to_dependency *) hash_find (s3_dependency_insn_hsh, name);
1c0d3aa6
NC
2207
2208 if (tmp)
2209 return tmp->type;
2210
c3b7224a 2211 return s3_D_all_insn;
1c0d3aa6
NC
2212}
2213
2214static int
c3b7224a 2215s3_check_dependency (char *pre_insn, char *pre_reg,
f9e53abc 2216 char *cur_insn, char *cur_reg, int *warn_or_error)
1c0d3aa6
NC
2217{
2218 int bubbles = 0;
2219 unsigned int i;
c3b7224a
NC
2220 enum s3_insn_type_for_dependency pre_insn_type;
2221 enum s3_insn_type_for_dependency cur_insn_type;
1c0d3aa6 2222
c3b7224a
NC
2223 pre_insn_type = s3_dependency_type_from_insn (pre_insn);
2224 cur_insn_type = s3_dependency_type_from_insn (cur_insn);
1c0d3aa6 2225
c3b7224a 2226 for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++)
1c0d3aa6 2227 {
c3b7224a
NC
2228 if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type)
2229 && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type
2230 || cur_insn_type == s3_data_dependency_table[i].cur_insn_type)
2231 && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0
2232 || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0)
2233 && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0
2234 || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0))
1c0d3aa6 2235 {
c3b7224a
NC
2236 bubbles = s3_data_dependency_table[i].bubblenum_3;
2237 *warn_or_error = s3_data_dependency_table[i].warn_or_error;
1c0d3aa6
NC
2238 break;
2239 }
2240 }
2241
2242 return bubbles;
2243}
2244
2245static void
c3b7224a 2246s3_build_one_frag (struct s3_score_it one_inst)
1c0d3aa6
NC
2247{
2248 char *p;
c3b7224a 2249 int relaxable_p = s3_g_opt;
1c0d3aa6
NC
2250 int relax_size = 0;
2251
2252 /* Start a new frag if frag_now is not empty. */
2253 if (frag_now_fix () != 0)
2254 {
2255 if (!frag_now->tc_frag_data.is_insn)
2256 frag_wane (frag_now);
2257
2258 frag_new (0);
2259 }
2260 frag_grow (20);
2261
2262 p = frag_more (one_inst.size);
c3b7224a 2263 s3_md_number_to_chars (p, one_inst.instruction, one_inst.size);
1c0d3aa6
NC
2264
2265#ifdef OBJ_ELF
2266 dwarf2_emit_insn (one_inst.size);
2267#endif
2268
2269 relaxable_p &= (one_inst.relax_size != 0);
2270 relax_size = relaxable_p ? one_inst.relax_size : 0;
2271
c3b7224a
NC
2272 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2273 s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
f9e53abc 2274 one_inst.type, 0, 0, relaxable_p),
1c0d3aa6
NC
2275 NULL, 0, NULL);
2276
2277 if (relaxable_p)
c3b7224a 2278 s3_md_number_to_chars (p, one_inst.relax_inst, relax_size);
1c0d3aa6
NC
2279}
2280
2281static void
c3b7224a 2282s3_handle_dependency (struct s3_score_it *theinst)
1c0d3aa6
NC
2283{
2284 int i;
2285 int warn_or_error = 0; /* warn - 0; error - 1 */
2286 int bubbles = 0;
2287 int remainder_bubbles = 0;
c3b7224a
NC
2288 char cur_insn[s3_INSN_NAME_LEN];
2289 char pre_insn[s3_INSN_NAME_LEN];
2290 struct s3_score_it nop_inst;
2291 struct s3_score_it pflush_inst;
1c0d3aa6
NC
2292
2293 nop_inst.instruction = 0x0000;
2294 nop_inst.size = 2;
2295 nop_inst.relax_inst = 0x80008000;
2296 nop_inst.relax_size = 4;
2297 nop_inst.type = NO16_OPD;
2298
2299 pflush_inst.instruction = 0x8000800a;
2300 pflush_inst.size = 4;
2301 pflush_inst.relax_inst = 0x8000;
2302 pflush_inst.relax_size = 0;
2303 pflush_inst.type = NO_OPD;
2304
2305 /* pflush will clear all data dependency. */
2306 if (strcmp (theinst->name, "pflush") == 0)
2307 {
c3b7224a 2308 s3_init_dependency_vector ();
1c0d3aa6
NC
2309 return;
2310 }
2311
c3b7224a
NC
2312 /* Push current instruction to s3_dependency_vector[0]. */
2313 for (i = s3_vector_size - 1; i > 0; i--)
2314 memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i]));
1c0d3aa6 2315
c3b7224a 2316 memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i]));
1c0d3aa6
NC
2317
2318 /* There is no dependency between nop and any instruction. */
c3b7224a
NC
2319 if (strcmp (s3_dependency_vector[0].name, "nop") == 0
2320 || strcmp (s3_dependency_vector[0].name, "nop!") == 0)
1c0d3aa6
NC
2321 return;
2322
c3b7224a 2323 strcpy (cur_insn, s3_dependency_vector[0].name);
1c0d3aa6 2324
c3b7224a 2325 for (i = 1; i < s3_vector_size; i++)
1c0d3aa6 2326 {
c3b7224a
NC
2327 /* The element of s3_dependency_vector is NULL. */
2328 if (s3_dependency_vector[i].name[0] == '\0')
1c0d3aa6
NC
2329 continue;
2330
c3b7224a 2331 strcpy (pre_insn, s3_dependency_vector[i].name);
1c0d3aa6 2332
c3b7224a 2333 bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg,
f9e53abc 2334 cur_insn, s3_dependency_vector[0].reg, &warn_or_error);
1c0d3aa6
NC
2335 remainder_bubbles = bubbles - i + 1;
2336
2337 if (remainder_bubbles > 0)
2338 {
2339 int j;
2340
c3b7224a 2341 if (s3_fix_data_dependency == 1)
1c0d3aa6
NC
2342 {
2343 if (remainder_bubbles <= 2)
2344 {
c3b7224a 2345 if (s3_warn_fix_data_dependency)
33eaf5de 2346 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
c3b7224a
NC
2347 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2348 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2349 remainder_bubbles, bubbles);
2350
c3b7224a
NC
2351 for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2352 memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles],
2353 sizeof (s3_dependency_vector[j]));
1c0d3aa6
NC
2354
2355 for (j = 1; j <= remainder_bubbles; j++)
2356 {
c3b7224a 2357 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
1c0d3aa6 2358 /* Insert nop!. */
c3b7224a 2359 s3_build_one_frag (nop_inst);
1c0d3aa6
NC
2360 }
2361 }
2362 else
2363 {
c3b7224a 2364 if (s3_warn_fix_data_dependency)
33eaf5de 2365 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
c3b7224a
NC
2366 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2367 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2368 bubbles);
2369
c3b7224a
NC
2370 for (j = 1; j < s3_vector_size; j++)
2371 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
1c0d3aa6
NC
2372
2373 /* Insert pflush. */
c3b7224a 2374 s3_build_one_frag (pflush_inst);
1c0d3aa6
NC
2375 }
2376 }
2377 else
2378 {
2379 if (warn_or_error)
2380 {
33eaf5de 2381 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
f9e53abc
NC
2382 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2383 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
2384 remainder_bubbles, bubbles);
1c0d3aa6
NC
2385 }
2386 else
2387 {
33eaf5de 2388 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
c3b7224a
NC
2389 s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
2390 s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
1c0d3aa6
NC
2391 remainder_bubbles, bubbles);
2392 }
2393 }
2394 }
2395 }
2396}
2397
2398static enum insn_class
c3b7224a 2399s3_get_insn_class_from_type (enum score_insn_type type)
1c0d3aa6 2400{
c3b7224a 2401 enum insn_class retval = (int) s3_FAIL;
1c0d3aa6
NC
2402
2403 switch (type)
2404 {
2405 case Rd_I4:
2406 case Rd_I5:
2407 case Rd_rvalueBP_I5:
2408 case Rd_lvalueBP_I5:
2409 case Rd_I8:
2410 case PC_DISP8div2:
2411 case PC_DISP11div2:
2412 case Rd_Rs:
2413 case Rd_HighRs:
2414 case Rd_lvalueRs:
2415 case Rd_rvalueRs:
2416 case x_Rs:
2417 case Rd_LowRs:
2418 case NO16_OPD:
c3b7224a
NC
2419 case Rd_SI5:
2420 case Rd_SI6:
1c0d3aa6
NC
2421 retval = INSN_CLASS_16;
2422 break;
2423 case Rd_Rs_I5:
2424 case x_Rs_I5:
2425 case x_I5_x:
2426 case Rd_Rs_I14:
2427 case I15:
2428 case Rd_I16:
2429 case Rd_SI16:
2430 case Rd_rvalueRs_SI10:
2431 case Rd_lvalueRs_SI10:
2432 case Rd_rvalueRs_preSI12:
2433 case Rd_rvalueRs_postSI12:
2434 case Rd_lvalueRs_preSI12:
2435 case Rd_lvalueRs_postSI12:
2436 case Rd_Rs_SI14:
2437 case Rd_rvalueRs_SI15:
2438 case Rd_lvalueRs_SI15:
2439 case PC_DISP19div2:
2440 case PC_DISP24div2:
2441 case Rd_Rs_Rs:
2442 case x_Rs_x:
2443 case x_Rs_Rs:
2444 case Rd_Rs_x:
2445 case Rd_x_Rs:
2446 case Rd_x_x:
2447 case OP5_rvalueRs_SI15:
2448 case I5_Rs_Rs_I5_OP5:
2449 case x_rvalueRs_post4:
2450 case Rd_rvalueRs_post4:
2451 case Rd_x_I5:
2452 case Rd_lvalueRs_post4:
2453 case x_lvalueRs_post4:
2454 case Rd_Rs_Rs_imm:
2455 case NO_OPD:
2456 case Rd_lvalue32Rs:
2457 case Rd_rvalue32Rs:
2458 case Insn_GP:
2459 case Insn_PIC:
b138abaa 2460 case Insn_internal:
c3b7224a
NC
2461 case Insn_BCMP:
2462 case Ra_I9_I5:
1c0d3aa6
NC
2463 retval = INSN_CLASS_32;
2464 break;
2465 case Insn_Type_PCE:
2466 retval = INSN_CLASS_PCE;
2467 break;
2468 case Insn_Type_SYN:
2469 retval = INSN_CLASS_SYN;
2470 break;
c3b7224a
NC
2471 case Rd_I30:
2472 case Rd_I32:
2473 retval = INSN_CLASS_48;
2474 break;
1c0d3aa6
NC
2475 default:
2476 abort ();
2477 break;
2478 }
2479 return retval;
2480}
2481
c3b7224a
NC
2482/* Type of p-bits:
2483 48-bit instruction: 1, 1, 0.
2484 32-bit instruction: 1, 0.
2485 16-bit instruction: 0. */
2486static bfd_vma
96d56e9f 2487s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class)
1c0d3aa6 2488{
c3b7224a
NC
2489 bfd_vma result = 0;
2490 bfd_vma m_code_high = 0;
2491 unsigned long m_code_middle = 0;
1c0d3aa6 2492 unsigned long m_code_low = 0;
c3b7224a
NC
2493 bfd_vma pb_high = 0;
2494 unsigned long pb_middle = 0;
1c0d3aa6
NC
2495 unsigned long pb_low = 0;
2496
96d56e9f 2497 if (i_class == INSN_CLASS_48)
c3b7224a
NC
2498 {
2499 pb_high = 0x800000000000LL;
2500 pb_middle = 0x80000000;
2501 pb_low = 0x00000000;
2502 m_code_high = m_code & 0x1fffc0000000LL;
2503 m_code_middle = m_code & 0x3fff8000;
2504 m_code_low = m_code & 0x00007fff;
2505 result = pb_high | (m_code_high << 2) |
f9e53abc
NC
2506 pb_middle | (m_code_middle << 1) |
2507 pb_low | m_code_low;
c3b7224a 2508 }
96d56e9f 2509 else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN)
1c0d3aa6
NC
2510 {
2511 pb_high = 0x80000000;
c3b7224a
NC
2512 pb_low = 0x00000000;
2513 m_code_high = m_code & 0x3fff8000;
2514 m_code_low = m_code & 0x00007fff;
2515 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
1c0d3aa6 2516 }
96d56e9f 2517 else if (i_class == INSN_CLASS_16)
1c0d3aa6
NC
2518 {
2519 pb_high = 0;
2520 pb_low = 0;
c3b7224a
NC
2521 m_code_high = m_code & 0x3fff8000;
2522 m_code_low = m_code & 0x00007fff;
2523 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
1c0d3aa6 2524 }
96d56e9f 2525 else if (i_class == INSN_CLASS_PCE)
1c0d3aa6 2526 {
c3b7224a 2527 /* Keep original. */
1c0d3aa6
NC
2528 pb_high = 0;
2529 pb_low = 0x00008000;
c3b7224a
NC
2530 m_code_high = m_code & 0x3fff8000;
2531 m_code_low = m_code & 0x00007fff;
2532 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
1c0d3aa6
NC
2533 }
2534 else
2535 {
2536 abort ();
2537 }
2538
1c0d3aa6 2539 return result;
1c0d3aa6
NC
2540}
2541
2542static void
c3b7224a 2543s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2)
1c0d3aa6
NC
2544{
2545 char *p;
2546 bfd_boolean pce_p = FALSE;
c3b7224a 2547 int relaxable_p = s3_g_opt;
1c0d3aa6 2548 int relax_size = 0;
c3b7224a
NC
2549 struct s3_score_it *inst1 = part_1;
2550 struct s3_score_it *inst2 = part_2;
2551 struct s3_score_it backup_inst1;
1c0d3aa6
NC
2552
2553 pce_p = (inst2) ? TRUE : FALSE;
c3b7224a 2554 memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it));
1c0d3aa6
NC
2555
2556 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2557 if (pce_p)
2558 {
2559 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
f9e53abc 2560 | (inst2->instruction & 0x7FFF);
c3b7224a 2561 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
1c0d3aa6 2562 backup_inst1.relax_inst = 0x8000;
c3b7224a 2563 backup_inst1.size = s3_INSN_SIZE;
1c0d3aa6
NC
2564 backup_inst1.relax_size = 0;
2565 backup_inst1.type = Insn_Type_PCE;
2566 }
2567 else
2568 {
c3b7224a 2569 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction,
f9e53abc 2570 s3_GET_INSN_CLASS (backup_inst1.type));
1c0d3aa6
NC
2571 }
2572
2573 if (backup_inst1.relax_size != 0)
2574 {
2575 enum insn_class tmp;
2576
c3b7224a
NC
2577 tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2578 backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp);
1c0d3aa6
NC
2579 }
2580
2581 /* Check data dependency. */
c3b7224a 2582 s3_handle_dependency (&backup_inst1);
1c0d3aa6
NC
2583
2584 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2585 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2586 if (frag_now_fix () != 0)
2587 {
2588 if (!frag_now->tc_frag_data.is_insn)
2589 frag_wane (frag_now);
2590
2591 frag_new (0);
2592 }
2593
2594 /* Here, we must call frag_grow in order to keep the instruction frag type is
2595 rs_machine_dependent.
2596 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
33eaf5de 2597 actually will call frag_wane.
1c0d3aa6
NC
2598 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2599 for frag_var. */
2600 frag_grow (20);
2601
2602 p = frag_more (backup_inst1.size);
c3b7224a 2603 s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
1c0d3aa6
NC
2604
2605#ifdef OBJ_ELF
2606 dwarf2_emit_insn (backup_inst1.size);
2607#endif
2608
2609 /* Generate fixup structure. */
2610 if (pce_p)
2611 {
2612 if (inst1->reloc.type != BFD_RELOC_NONE)
c3b7224a 2613 s3_fix_new_score (frag_now, p - frag_now->fr_literal,
f9e53abc
NC
2614 inst1->size, &inst1->reloc.exp,
2615 inst1->reloc.pc_rel, inst1->reloc.type);
1c0d3aa6
NC
2616
2617 if (inst2->reloc.type != BFD_RELOC_NONE)
c3b7224a 2618 s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
f9e53abc 2619 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
1c0d3aa6
NC
2620 }
2621 else
2622 {
2623 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
c3b7224a 2624 s3_fix_new_score (frag_now, p - frag_now->fr_literal,
f9e53abc
NC
2625 backup_inst1.size, &backup_inst1.reloc.exp,
2626 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
1c0d3aa6
NC
2627 }
2628
2629 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2630 relaxable_p &= (backup_inst1.relax_size != 0);
2631 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2632
c3b7224a
NC
2633 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
2634 s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
f9e53abc 2635 backup_inst1.type, 0, 0, relaxable_p),
1c0d3aa6
NC
2636 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2637
2638 if (relaxable_p)
c3b7224a 2639 s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
1c0d3aa6 2640
c3b7224a 2641 memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it));
1c0d3aa6
NC
2642}
2643
2644static void
c3b7224a 2645s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
1c0d3aa6
NC
2646{
2647 char c;
2648 char *p;
2649 char *operator = insnstr;
c3b7224a 2650 const struct s3_asm_opcode *opcode;
1c0d3aa6
NC
2651
2652 /* Parse operator and operands. */
c3b7224a 2653 s3_skip_whitespace (operator);
1c0d3aa6
NC
2654
2655 for (p = operator; *p != '\0'; p++)
2656 if ((*p == ' ') || (*p == '!'))
2657 break;
2658
2659 if (*p == '!')
2660 p++;
2661
2662 c = *p;
2663 *p = '\0';
2664
c3b7224a
NC
2665 opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
2666 *p = c;
2667
2668 memset (&s3_inst, '\0', sizeof (s3_inst));
2669 sprintf (s3_inst.str, "%s", insnstr);
2670 if (opcode)
2671 {
2672 s3_inst.instruction = opcode->value;
2673 s3_inst.relax_inst = opcode->relax_value;
2674 s3_inst.type = opcode->type;
2675 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2676 s3_inst.relax_size = 0;
2677 s3_inst.bwarn = 0;
d3ce72d0 2678 sprintf (s3_inst.name, "%s", opcode->template_name);
c3b7224a
NC
2679 strcpy (s3_inst.reg, "");
2680 s3_inst.error = NULL;
2681 s3_inst.reloc.type = BFD_RELOC_NONE;
2682
2683 (*opcode->parms) (p);
2684
2685 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */
2686 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2687 s3_gen_insn_frag (&s3_inst, NULL);
2688 }
2689 else
2690 s3_inst.error = _("unrecognized opcode");
2691}
2692
2693static void
2694s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p)
2695{
2696 char c;
2697 char *p;
2698 char *operator = insnstr;
2699 const struct s3_asm_opcode *opcode;
2700
2701 /* Parse operator and operands. */
2702 s3_skip_whitespace (operator);
2703
2704 for (p = operator; *p != '\0'; p++)
2705 if (*p == ' ')
2706 break;
2707
2708 c = *p;
2709 *p = '\0';
2710
2711 opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
1c0d3aa6
NC
2712 *p = c;
2713
c3b7224a
NC
2714 memset (&s3_inst, '\0', sizeof (s3_inst));
2715 sprintf (s3_inst.str, "%s", insnstr);
1c0d3aa6
NC
2716 if (opcode)
2717 {
c3b7224a
NC
2718 s3_inst.instruction = opcode->value;
2719 s3_inst.relax_inst = opcode->relax_value;
2720 s3_inst.type = opcode->type;
2721 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
2722 s3_inst.relax_size = 0;
2723 s3_inst.bwarn = 0;
d3ce72d0 2724 sprintf (s3_inst.name, "%s", opcode->template_name);
c3b7224a
NC
2725 strcpy (s3_inst.reg, "");
2726 s3_inst.error = NULL;
2727 s3_inst.reloc.type = BFD_RELOC_NONE;
1c0d3aa6
NC
2728
2729 (*opcode->parms) (p);
2730
c3b7224a
NC
2731 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */
2732 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
2733 s3_gen_insn_frag (&s3_inst, NULL);
1c0d3aa6
NC
2734 }
2735 else
c3b7224a 2736 s3_inst.error = _("unrecognized opcode");
1c0d3aa6
NC
2737}
2738
2739static int
c3b7224a 2740s3_append_insn (char *str, bfd_boolean gen_frag_p)
1c0d3aa6 2741{
c3b7224a 2742 int retval = s3_SUCCESS;
1c0d3aa6 2743
c3b7224a 2744 s3_parse_16_32_inst (str, gen_frag_p);
1c0d3aa6 2745
c3b7224a 2746 if (s3_inst.error)
1c0d3aa6 2747 {
c3b7224a
NC
2748 retval = (int) s3_FAIL;
2749 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
2750 s3_inst.error = NULL;
1c0d3aa6
NC
2751 }
2752
2753 return retval;
2754}
2755
1c0d3aa6 2756static void
c3b7224a 2757s3_do16_mv_cmp (char *str)
1c0d3aa6 2758{
c3b7224a 2759 s3_skip_whitespace (str);
1c0d3aa6 2760
c3b7224a
NC
2761 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2762 || s3_skip_past_comma (&str) == (int) s3_FAIL
2763 || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2764 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
2765 {
2766 return;
2767 }
c3b7224a 2768}
1c0d3aa6 2769
c3b7224a
NC
2770static void
2771s3_do16_cmpi (char *str)
2772{
2773 s3_skip_whitespace (str);
1c0d3aa6 2774
c3b7224a
NC
2775 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
2776 || s3_skip_past_comma (&str) == (int) s3_FAIL
2777 || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL
2778 || s3_end_of_line (str) == (int) s3_FAIL)
2779 {
2780 return;
1c0d3aa6
NC
2781 }
2782}
2783
2784static void
c3b7224a 2785s3_do16_addi (char *str)
1c0d3aa6 2786{
c3b7224a 2787 s3_skip_whitespace (str);
1c0d3aa6 2788
c3b7224a
NC
2789 if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL
2790 || s3_skip_past_comma (&str) == (int) s3_FAIL
2791 || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL
2792 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
2793 {
2794 return;
2795 }
1c0d3aa6
NC
2796}
2797
c3b7224a 2798/* Handle bitclr! / bitset! / bittst! / bittgl! */
1c0d3aa6 2799static void
c3b7224a 2800s3_do16_rdi5 (char *str)
1c0d3aa6 2801{
c3b7224a 2802 s3_skip_whitespace (str);
1c0d3aa6 2803
c3b7224a
NC
2804 if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL
2805 || s3_skip_past_comma (&str) == (int) s3_FAIL
2806 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
2807 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
2808 return;
2809 else
2810 {
c3b7224a
NC
2811 s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20)
2812 | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10);
2813 s3_inst.relax_size = 4;
1c0d3aa6
NC
2814 }
2815}
2816
c3b7224a
NC
2817
2818/* Handle sdbbp!. */
1c0d3aa6 2819static void
c3b7224a 2820s3_do16_xi5 (char *str)
1c0d3aa6 2821{
c3b7224a 2822 s3_skip_whitespace (str);
1c0d3aa6 2823
c3b7224a 2824 if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 2825 return;
1c0d3aa6
NC
2826}
2827
2828/* Check that an immediate is word alignment or half word alignment.
2829 If so, convert it to the right format. */
2830static int
c3b7224a 2831s3_validate_immediate_align (int val, unsigned int data_type)
1c0d3aa6
NC
2832{
2833 if (data_type == _IMM5_RSHIFT_1)
2834 {
2835 if (val % 2)
2836 {
c3b7224a
NC
2837 s3_inst.error = _("address offset must be half word alignment");
2838 return (int) s3_FAIL;
1c0d3aa6
NC
2839 }
2840 }
2841 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2842 {
2843 if (val % 4)
2844 {
c3b7224a
NC
2845 s3_inst.error = _("address offset must be word alignment");
2846 return (int) s3_FAIL;
1c0d3aa6
NC
2847 }
2848 }
2849
c3b7224a 2850 return s3_SUCCESS;
1c0d3aa6
NC
2851}
2852
2853static int
c3b7224a 2854s3_exp_ldst_offset (char **str, int shift, unsigned int data_type)
1c0d3aa6
NC
2855{
2856 char *dataptr;
2857
2858 dataptr = * str;
2859
2860 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2861 && (data_type != _SIMM16_LA)
2862 && (data_type != _VALUE_HI16)
2863 && (data_type != _VALUE_LO16)
2864 && (data_type != _IMM16)
2865 && (data_type != _IMM15)
2866 && (data_type != _IMM14)
2867 && (data_type != _IMM4)
2868 && (data_type != _IMM5)
2869 && (data_type != _IMM8)
2870 && (data_type != _IMM5_RSHIFT_1)
2871 && (data_type != _IMM5_RSHIFT_2)
2872 && (data_type != _SIMM14_NEG)
2873 && (data_type != _IMM10_RSHIFT_2))
2874 {
2875 data_type += 24;
2876 }
2877
c3b7224a
NC
2878 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
2879 return (int) s3_FAIL;
1c0d3aa6 2880
c3b7224a 2881 if (s3_inst.reloc.exp.X_op == O_constant)
1c0d3aa6
NC
2882 {
2883 /* Need to check the immediate align. */
c3b7224a 2884 int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type);
1c0d3aa6 2885
c3b7224a
NC
2886 if (value == (int) s3_FAIL)
2887 return (int) s3_FAIL;
1c0d3aa6 2888
c3b7224a
NC
2889 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
2890 if (value == (int) s3_FAIL)
1c0d3aa6 2891 {
1c0d3aa6 2892 if (data_type < 30)
c3b7224a 2893 sprintf (s3_err_msg,
14119072 2894 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
2895 s3_score_df_range[data_type].bits,
2896 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
1c0d3aa6 2897 else
c3b7224a 2898 sprintf (s3_err_msg,
14119072 2899 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
2900 s3_score_df_range[data_type - 24].bits,
2901 s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]);
2902 s3_inst.error = s3_err_msg;
2903 return (int) s3_FAIL;
1c0d3aa6
NC
2904 }
2905
2906 if (data_type == _IMM5_RSHIFT_1)
2907 {
2908 value >>= 1;
2909 }
2910 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2911 {
2912 value >>= 2;
2913 }
2914
c3b7224a 2915 if (s3_score_df_range[data_type].range[0] != 0)
1c0d3aa6 2916 {
c3b7224a 2917 value &= (1 << s3_score_df_range[data_type].bits) - 1;
1c0d3aa6
NC
2918 }
2919
c3b7224a 2920 s3_inst.instruction |= value << shift;
1c0d3aa6
NC
2921 }
2922 else
2923 {
c3b7224a 2924 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
2925 }
2926
c3b7224a 2927 return s3_SUCCESS;
1c0d3aa6
NC
2928}
2929
2930static void
c3b7224a 2931s3_do_ldst_insn (char *str)
1c0d3aa6
NC
2932{
2933 int pre_inc = 0;
2934 int conflict_reg;
2935 int value;
2936 char * temp;
1c0d3aa6
NC
2937 char *dataptr;
2938 int reg;
2939 int ldst_idx = 0;
2940
c3b7224a 2941 s3_skip_whitespace (str);
1c0d3aa6 2942
c3b7224a
NC
2943 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
2944 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
2945 return;
2946
2947 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
2948 if (*str == '[')
2949 {
2950 str++;
c3b7224a 2951 s3_skip_whitespace (str);
1c0d3aa6 2952
c3b7224a 2953 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
2954 return;
2955
2956 /* Conflicts can occur on stores as well as loads. */
2957 conflict_reg = (conflict_reg == reg);
c3b7224a 2958 s3_skip_whitespace (str);
1c0d3aa6
NC
2959 temp = str + 1; /* The latter will process decimal/hex expression. */
2960
2961 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
2962 if (*str == ']')
2963 {
2964 str++;
2965 if (*str == '+')
2966 {
2967 str++;
2968 /* ld/sw rD, [rA]+, simm12. */
c3b7224a 2969 if (s3_skip_past_comma (&str) == s3_SUCCESS)
1c0d3aa6 2970 {
c3b7224a
NC
2971 if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL)
2972 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
2973 return;
2974
2975 if (conflict_reg)
2976 {
c3b7224a 2977 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
1c0d3aa6
NC
2978
2979 if ((ldst_func == INSN_LH)
2980 || (ldst_func == INSN_LHU)
2981 || (ldst_func == INSN_LW)
2982 || (ldst_func == INSN_LB)
2983 || (ldst_func == INSN_LBU))
2984 {
c3b7224a 2985 s3_inst.error = _("register same as write-back base");
1c0d3aa6
NC
2986 return;
2987 }
2988 }
2989
c3b7224a
NC
2990 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
2991 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2992 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
1c0d3aa6
NC
2993
2994 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
c3b7224a 2995 if ((s3_inst.instruction & 0x3e000007) == 0x0e000000)
1c0d3aa6 2996 {
c3b7224a
NC
2997 /* rs = r0, offset = 4 */
2998 if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
2999 && (((s3_inst.instruction >> 3) & 0xfff) == 4))
1c0d3aa6 3000 {
c3b7224a
NC
3001 /* Relax to pop!. */
3002 s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f);
3003 s3_inst.relax_size = 2;
1c0d3aa6
NC
3004 }
3005 }
3006 return;
3007 }
3008 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3009 else
3010 {
c3b7224a
NC
3011 s3_SET_INSN_ERROR (NULL);
3012 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3013 {
3014 return;
3015 }
3016
3017 pre_inc = 1;
c3b7224a
NC
3018 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0);
3019 value &= (1 << s3_score_df_range[_SIMM12].bits) - 1;
3020 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3021 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3022 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3023 s3_inst.instruction |= value << 3;
3024 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3025 return;
3026 }
3027 }
3028 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3029 else
3030 {
c3b7224a 3031 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3032 return;
3033
c3b7224a
NC
3034 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3035 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3036 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
1c0d3aa6
NC
3037
3038 /* lbu rd, [rs] -> lbu! rd, [rs] */
3039 if (ldst_idx == INSN_LBU)
3040 {
c3b7224a 3041 s3_inst.relax_inst = INSN16_LBU;
1c0d3aa6
NC
3042 }
3043 else if (ldst_idx == INSN_LH)
3044 {
c3b7224a 3045 s3_inst.relax_inst = INSN16_LH;
1c0d3aa6
NC
3046 }
3047 else if (ldst_idx == INSN_LW)
3048 {
c3b7224a 3049 s3_inst.relax_inst = INSN16_LW;
1c0d3aa6
NC
3050 }
3051 else if (ldst_idx == INSN_SB)
3052 {
c3b7224a 3053 s3_inst.relax_inst = INSN16_SB;
1c0d3aa6
NC
3054 }
3055 else if (ldst_idx == INSN_SH)
3056 {
c3b7224a 3057 s3_inst.relax_inst = INSN16_SH;
1c0d3aa6
NC
3058 }
3059 else if (ldst_idx == INSN_SW)
3060 {
c3b7224a 3061 s3_inst.relax_inst = INSN16_SW;
1c0d3aa6
NC
3062 }
3063 else
3064 {
c3b7224a 3065 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3066 }
3067
3068 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
c3b7224a 3069 /* if ((ldst_idx == INSN_LBU)
f9e53abc
NC
3070 || (ldst_idx == INSN_LH)
3071 || (ldst_idx == INSN_LW)
3072 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/
c3b7224a 3073 if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW))
1c0d3aa6 3074 {
c3b7224a
NC
3075 /* ra only 3 bit , rd only 4 bit for lw! and sw! */
3076 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 3077 {
c3b7224a
NC
3078 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) |
3079 (((s3_inst.instruction >> 15) & 0x7) << 5);
3080 s3_inst.relax_size = 2;
1c0d3aa6
NC
3081 }
3082 }
3083
3084 return;
3085 }
3086 }
3087 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3088 else
3089 {
c3b7224a 3090 if (s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6 3091 {
c3b7224a 3092 s3_inst.error = _("pre-indexed expression expected");
1c0d3aa6
NC
3093 return;
3094 }
3095
c3b7224a 3096 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
1c0d3aa6
NC
3097 return;
3098
c3b7224a 3099 s3_skip_whitespace (str);
1c0d3aa6
NC
3100 if (*str++ != ']')
3101 {
c3b7224a 3102 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3103 return;
3104 }
3105
c3b7224a 3106 s3_skip_whitespace (str);
1c0d3aa6
NC
3107 /* ld/sw rD, [rA, simm12]+. */
3108 if (*str == '+')
3109 {
3110 str++;
3111 pre_inc = 1;
3112 if (conflict_reg)
3113 {
c3b7224a 3114 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
1c0d3aa6
NC
3115
3116 if ((ldst_func == INSN_LH)
3117 || (ldst_func == INSN_LHU)
3118 || (ldst_func == INSN_LW)
3119 || (ldst_func == INSN_LB)
3120 || (ldst_func == INSN_LBU))
3121 {
c3b7224a 3122 s3_inst.error = _("register same as write-back base");
1c0d3aa6
NC
3123 return;
3124 }
3125 }
3126 }
3127
c3b7224a 3128 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3129 return;
3130
c3b7224a 3131 if (s3_inst.reloc.exp.X_op == O_constant)
1c0d3aa6 3132 {
1c0d3aa6
NC
3133 unsigned int data_type;
3134
3135 if (pre_inc == 1)
3136 data_type = _SIMM12;
3137 else
3138 data_type = _SIMM15;
3139 dataptr = temp;
3140
3141 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
3142 && (data_type != _SIMM16_LA)
3143 && (data_type != _VALUE_HI16)
3144 && (data_type != _VALUE_LO16)
3145 && (data_type != _IMM16)
3146 && (data_type != _IMM15)
3147 && (data_type != _IMM14)
3148 && (data_type != _IMM4)
3149 && (data_type != _IMM5)
3150 && (data_type != _IMM8)
3151 && (data_type != _IMM5_RSHIFT_1)
3152 && (data_type != _IMM5_RSHIFT_2)
3153 && (data_type != _SIMM14_NEG)
3154 && (data_type != _IMM10_RSHIFT_2))
3155 {
3156 data_type += 24;
3157 }
3158
c3b7224a
NC
3159 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3160 if (value == (int) s3_FAIL)
1c0d3aa6 3161 {
b138abaa 3162 if (data_type < 30)
c3b7224a 3163 sprintf (s3_err_msg,
14119072 3164 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
3165 s3_score_df_range[data_type].bits,
3166 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
1c0d3aa6 3167 else
c3b7224a 3168 sprintf (s3_err_msg,
14119072 3169 _("invalid constant: %d bit expression not in range %d..%d"),
c3b7224a
NC
3170 s3_score_df_range[data_type - 24].bits,
3171 s3_score_df_range[data_type - 24].range[0],
3172 s3_score_df_range[data_type - 24].range[1]);
3173 s3_inst.error = s3_err_msg;
1c0d3aa6
NC
3174 return;
3175 }
3176
c3b7224a
NC
3177 value &= (1 << s3_score_df_range[data_type].bits) - 1;
3178 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3179 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3180 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
1c0d3aa6 3181 if (pre_inc == 1)
c3b7224a 3182 s3_inst.instruction |= value << 3;
1c0d3aa6 3183 else
c3b7224a 3184 s3_inst.instruction |= value;
1c0d3aa6
NC
3185
3186 /* lw rD, [rA, simm15] */
c3b7224a 3187 if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
1c0d3aa6 3188 {
c3b7224a
NC
3189 /* rD in [r0 - r15]. , ra in [r0-r7] */
3190 if ((((s3_inst.instruction >> 15) & 0x18) == 0)
3191 && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 3192 {
c3b7224a
NC
3193 /* simm = [bit 7], lw -> lw!. */
3194 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
1c0d3aa6 3195 {
c3b7224a
NC
3196 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5)
3197 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3198 s3_inst.relax_size = 2;
1c0d3aa6
NC
3199 }
3200 else
3201 {
c3b7224a 3202 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3203 }
3204 }
3205 else
3206 {
c3b7224a 3207 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3208 }
3209 }
3210 /* sw rD, [rA, simm15] */
c3b7224a 3211 else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
1c0d3aa6 3212 {
c3b7224a
NC
3213 /* rD is in [r0 - r15] and ra in [r0-r7] */
3214 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
1c0d3aa6 3215 {
c3b7224a
NC
3216 /* simm15 =7 bit , sw -> sw!. */
3217 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
1c0d3aa6 3218 {
c3b7224a
NC
3219 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5)
3220 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3221 s3_inst.relax_size = 2;
1c0d3aa6
NC
3222 }
3223 /* rA = r2, sw -> swp!. */
1c0d3aa6
NC
3224 else
3225 {
c3b7224a 3226 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3227 }
3228 }
3229 else
3230 {
c3b7224a 3231 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3232 }
3233 }
3234 /* sw rD, [rA, simm15]+ sw pre. */
c3b7224a 3235 else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
1c0d3aa6 3236 {
c3b7224a
NC
3237 /* simm15 = -4. and ra==r0 */
3238 if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3239 && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
1c0d3aa6 3240 {
1c0d3aa6 3241 /* sw -> push!. */
c3b7224a
NC
3242 s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
3243 s3_inst.relax_size = 2;
1c0d3aa6
NC
3244 }
3245 else
3246 {
c3b7224a 3247 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3248 }
3249 }
3250 else
3251 {
c3b7224a 3252 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
3253 }
3254
3255 return;
3256 }
3257 else
3258 {
3259 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
c3b7224a 3260 s3_inst.reloc.pc_rel = 0;
1c0d3aa6
NC
3261 }
3262 }
3263 }
3264 else
3265 {
c3b7224a 3266 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3267 }
3268}
3269
3270/* Handle cache. */
1c0d3aa6 3271static void
c3b7224a 3272s3_do_cache (char *str)
1c0d3aa6 3273{
c3b7224a 3274 s3_skip_whitespace (str);
1c0d3aa6 3275
c3b7224a 3276 if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3277 {
3278 return;
3279 }
3280 else
3281 {
3282 int cache_op;
3283
c3b7224a
NC
3284 cache_op = (s3_inst.instruction >> 20) & 0x1F;
3285 sprintf (s3_inst.name, "cache %d", cache_op);
1c0d3aa6
NC
3286 }
3287
3288 if (*str == '[')
3289 {
3290 str++;
c3b7224a 3291 s3_skip_whitespace (str);
1c0d3aa6 3292
c3b7224a 3293 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3294 return;
3295
c3b7224a 3296 s3_skip_whitespace (str);
1c0d3aa6
NC
3297
3298 /* cache op, [rA] */
c3b7224a 3299 if (s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6 3300 {
c3b7224a 3301 s3_SET_INSN_ERROR (NULL);
1c0d3aa6
NC
3302 if (*str != ']')
3303 {
c3b7224a 3304 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3305 return;
3306 }
3307 str++;
3308 }
3309 /* cache op, [rA, simm15] */
3310 else
3311 {
c3b7224a 3312 if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
1c0d3aa6
NC
3313 {
3314 return;
3315 }
3316
c3b7224a 3317 s3_skip_whitespace (str);
1c0d3aa6
NC
3318 if (*str++ != ']')
3319 {
c3b7224a 3320 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3321 return;
3322 }
3323 }
3324
c3b7224a 3325 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3326 return;
3327 }
3328 else
3329 {
c3b7224a 3330 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3331 }
3332}
3333
3334static void
c3b7224a 3335s3_do_crdcrscrsimm5 (char *str)
1c0d3aa6
NC
3336{
3337 char *strbak;
3338
3339 strbak = str;
c3b7224a 3340 s3_skip_whitespace (str);
1c0d3aa6 3341
c3b7224a
NC
3342 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3343 || s3_skip_past_comma (&str) == (int) s3_FAIL
3344 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3345 || s3_skip_past_comma (&str) == (int) s3_FAIL
3346 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3347 || s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6
NC
3348 {
3349 str = strbak;
3350 /* cop1 cop_code20. */
c3b7224a 3351 if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
1c0d3aa6
NC
3352 return;
3353 }
3354 else
3355 {
c3b7224a 3356 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
1c0d3aa6
NC
3357 return;
3358 }
3359
c3b7224a 3360 s3_end_of_line (str);
1c0d3aa6
NC
3361}
3362
3363/* Handle ldc/stc. */
3364static void
c3b7224a 3365s3_do_ldst_cop (char *str)
1c0d3aa6 3366{
c3b7224a 3367 s3_skip_whitespace (str);
1c0d3aa6 3368
c3b7224a
NC
3369 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL)
3370 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3371 return;
3372
3373 if (*str == '[')
3374 {
3375 str++;
c3b7224a 3376 s3_skip_whitespace (str);
1c0d3aa6 3377
c3b7224a 3378 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3379 return;
3380
c3b7224a 3381 s3_skip_whitespace (str);
1c0d3aa6
NC
3382
3383 if (*str++ != ']')
3384 {
c3b7224a 3385 if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
1c0d3aa6
NC
3386 return;
3387
c3b7224a 3388 s3_skip_whitespace (str);
1c0d3aa6
NC
3389 if (*str++ != ']')
3390 {
c3b7224a 3391 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3392 return;
3393 }
3394 }
3395
c3b7224a 3396 s3_end_of_line (str);
1c0d3aa6
NC
3397 }
3398 else
c3b7224a 3399 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3400}
3401
3402static void
c3b7224a 3403s3_do16_ldst_insn (char *str)
1c0d3aa6 3404{
f9e53abc 3405 int conflict_reg = 0;
c3b7224a 3406 s3_skip_whitespace (str);
1c0d3aa6 3407
c3b7224a 3408 if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3409 return;
3410
3411 if (*str == '[')
3412 {
1c0d3aa6
NC
3413
3414 str++;
c3b7224a 3415 s3_skip_whitespace (str);
1c0d3aa6 3416
c3b7224a 3417 if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
1c0d3aa6 3418 return;
c3b7224a
NC
3419 if (conflict_reg&0x8)
3420 {
3421 sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
f9e53abc
NC
3422 s3_inst.error = s3_err_msg;
3423 return;
c3b7224a 3424 }
1c0d3aa6 3425
c3b7224a 3426 s3_skip_whitespace (str);
f9e53abc 3427
c3b7224a 3428 if (*str == ']')
1c0d3aa6 3429 {
c3b7224a
NC
3430 str++;
3431 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 3432 return;
1c0d3aa6
NC
3433 }
3434 else
3435 {
c3b7224a
NC
3436 if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3437 {
3438 s3_inst.error = _("comma is expected");
3439 return;
3440 }
3441 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3442 return;
3443 s3_skip_whitespace (str);
3444 if (*str++ != ']')
3445 {
3446 s3_inst.error = _("missing ]");
3447 return;
3448 }
3449 if (s3_end_of_line (str) == (int) s3_FAIL)
3450 return;
3451 if (s3_inst.reloc.exp.X_op == O_constant)
3452 {
3453 int value;
3454 unsigned int data_type;
3455 data_type = _IMM5_RSHIFT_2;
3456 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3457 if (value == (int) s3_FAIL)
f9e53abc
NC
3458 {
3459 if (data_type < 30)
3460 sprintf (s3_err_msg,
3461 _("invalid constant: %d bit expression not in range %d..%d"),
3462 s3_score_df_range[data_type].bits,
3463 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
c3b7224a
NC
3464 s3_inst.error = s3_err_msg;
3465 return;
3466 }
f9e53abc 3467 if (value & 0x3)
c3b7224a
NC
3468 {
3469 sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value);
f9e53abc
NC
3470 s3_inst.error = s3_err_msg;
3471 return;
c3b7224a
NC
3472 }
3473
f9e53abc 3474 value >>= 2;
c3b7224a
NC
3475 s3_inst.instruction |= value;
3476 }
1c0d3aa6
NC
3477 }
3478 }
3479 else
3480 {
c3b7224a 3481 sprintf (s3_err_msg, _("missing ["));
f9e53abc
NC
3482 s3_inst.error = s3_err_msg;
3483 return;
1c0d3aa6
NC
3484 }
3485}
3486
1c0d3aa6 3487static void
c3b7224a 3488s3_do_lw48 (char *str)
1c0d3aa6 3489{
c3b7224a 3490 bfd_signed_vma val = 0;
1c0d3aa6 3491
c3b7224a 3492 s3_skip_whitespace (str);
1c0d3aa6 3493
c3b7224a
NC
3494 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3495 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3496 return;
3497
c3b7224a
NC
3498 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3499 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 3500 {
c3b7224a 3501 return;
1c0d3aa6
NC
3502 }
3503
c3b7224a
NC
3504 /* Check word align for lw48 rd, value. */
3505 if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3506 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3507 {
3508 s3_inst.error = _("invalid constant: 32 bit expression not word align");
3509 return;
3510 }
1c0d3aa6 3511
c3b7224a
NC
3512 /* Check and set offset. */
3513 val = s3_inst.reloc.exp.X_add_number;
3514 if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3515 && (!(val >= 0 && val <= 0xffffffffLL)))
3516 {
3517 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3518 return;
3519 }
1c0d3aa6 3520
c3b7224a
NC
3521 val &= 0xffffffff;
3522 val >>= 2;
3523 s3_inst.instruction |= (val << 7);
1c0d3aa6 3524
c3b7224a
NC
3525 /* Set reloc type. */
3526 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
1c0d3aa6 3527
1c0d3aa6
NC
3528}
3529
3530static void
c3b7224a 3531s3_do_sw48 (char *str)
1c0d3aa6 3532{
c3b7224a 3533 bfd_signed_vma val = 0;
1c0d3aa6 3534
c3b7224a 3535 s3_skip_whitespace (str);
1c0d3aa6 3536
c3b7224a
NC
3537 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3538 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3539 return;
1c0d3aa6 3540
c3b7224a
NC
3541 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3542 || s3_end_of_line (str) == (int) s3_FAIL)
3543 {
3544 return;
3545 }
1c0d3aa6 3546
c3b7224a
NC
3547 /* Check word align for lw48 rd, value. */
3548 if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3549 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3550 {
3551 s3_inst.error = _("invalid constant: 32 bit expression not word align");
3552 return;
3553 }
1c0d3aa6 3554
c3b7224a
NC
3555 /* Check and set offset. */
3556 val = s3_inst.reloc.exp.X_add_number;
3557 if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3558 && (!(val >= 0 && val <= 0xffffffffLL)))
1c0d3aa6 3559 {
c3b7224a
NC
3560 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3561 return;
3562 }
1c0d3aa6 3563
c3b7224a
NC
3564 val &= 0xffffffff;
3565 val >>= 2;
3566 s3_inst.instruction |= (val << 7);
1c0d3aa6 3567
c3b7224a
NC
3568 /* Set reloc type. */
3569 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3570}
1c0d3aa6 3571
c3b7224a
NC
3572static void
3573s3_do_ldi48 (char *str)
3574{
3575 bfd_signed_vma val;
1c0d3aa6 3576
c3b7224a 3577 s3_skip_whitespace (str);
1c0d3aa6 3578
c3b7224a
NC
3579 if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL
3580 || s3_skip_past_comma (&str) == (int) s3_FAIL)
3581 return;
3582
3583 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3584 || s3_end_of_line (str) == (int) s3_FAIL)
3585 {
3586 return;
1c0d3aa6 3587 }
c3b7224a
NC
3588
3589 /* Check and set offset. */
3590 val = s3_inst.reloc.exp.X_add_number;
3591 if (!(val >= -0xffffffffLL && val <= 0xffffffffLL))
3592 {
3593 s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]");
3594 return;
3595 }
3596
3597 val &= 0xffffffff;
3598 s3_inst.instruction |= (val << 5);
3599
3600 /* Set reloc type. */
3601 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32;
3602}
3603
3604static void
3605s3_do_sdbbp48 (char *str)
3606{
3607 s3_skip_whitespace (str);
3608
3609 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
3610 return;
3611}
3612
3613static void
3614s3_do_and48 (char *str)
3615{
3616 s3_skip_whitespace (str);
3617
3618 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3619 || s3_skip_past_comma (&str) == (int) s3_FAIL
3620 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3621 || s3_skip_past_comma (&str) == (int) s3_FAIL
3622 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3623 || s3_end_of_line (str) == (int) s3_FAIL)
3624 return;
3625}
3626
3627static void
3628s3_do_or48 (char *str)
3629{
3630 s3_skip_whitespace (str);
3631
3632 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3633 || s3_skip_past_comma (&str) == (int) s3_FAIL
3634 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3635 || s3_skip_past_comma (&str) == (int) s3_FAIL
3636 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3637 || s3_end_of_line (str) == (int) s3_FAIL)
3638 return;
3639}
3640
f9e53abc 3641static void
c3b7224a
NC
3642s3_do_mbitclr (char *str)
3643{
3644 int val;
3645 s3_skip_whitespace (str);
3646
3647 if (*str != '[')
3648 {
3649 sprintf (s3_err_msg, _("missing ["));
f9e53abc 3650 s3_inst.error = s3_err_msg;
c3b7224a
NC
3651 return;
3652 }
3653 str++;
3654
3655 s3_inst.instruction &= 0x0;
3656
3657 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3658 || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3659 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3660 return;
3661
3662 /* Get imm11 and refill opcode. */
3663 val = s3_inst.instruction & 0x7ff;
3664 val >>= 2;
3665 s3_inst.instruction &= 0x000f8000;
3666 s3_inst.instruction |= 0x00000064;
3667
3668 if (*str != ']')
3669 {
3670 sprintf (s3_err_msg, _("missing ]"));
f9e53abc 3671 s3_inst.error = s3_err_msg;
c3b7224a
NC
3672 return;
3673 }
3674 str++;
3675
3676 if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3677 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3678 return;
3679
3680 /* Set imm11 to opcode. */
3681 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
3682 | (((val >> 1 ) & 0x7) << 7)
3683 | (((val >> 4 ) & 0x1f) << 20);
c3b7224a
NC
3684}
3685
f9e53abc 3686static void
c3b7224a
NC
3687s3_do_mbitset (char *str)
3688{
3689 int val;
3690 s3_skip_whitespace (str);
3691
3692 if (*str != '[')
1c0d3aa6 3693 {
c3b7224a 3694 sprintf (s3_err_msg, _("missing ["));
f9e53abc 3695 s3_inst.error = s3_err_msg;
c3b7224a
NC
3696 return;
3697 }
3698 str++;
3699
3700 s3_inst.instruction &= 0x0;
3701
3702 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3703 || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3704 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3705 return;
3706
3707 /* Get imm11 and refill opcode. */
3708 val = s3_inst.instruction & 0x7ff;
3709 val >>= 2;
3710 s3_inst.instruction &= 0x000f8000;
3711 s3_inst.instruction |= 0x0000006c;
3712
3713 if (*str != ']')
3714 {
3715 sprintf (s3_err_msg, _("missing ]"));
f9e53abc 3716 s3_inst.error = s3_err_msg;
c3b7224a
NC
3717 return;
3718 }
3719 str++;
3720
3721 if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3722 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3723 return;
3724
3725 /* Set imm11 to opcode. */
3726 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
3727 | (((val >> 1 ) & 0x7) << 7)
3728 | (((val >> 4 ) & 0x1f) << 20);
c3b7224a
NC
3729}
3730
3731static void
3732s3_do16_slli_srli (char *str)
3733{
3734 s3_skip_whitespace (str);
3735
3736 if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL)
3737 || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3738 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
f9e53abc 3739 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3740 return;
3741}
3742
3743static void
3744s3_do16_ldiu (char *str)
3745{
3746 s3_skip_whitespace (str);
3747
3748 if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3749 || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3750 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
f9e53abc 3751 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3752 return;
3753}
3754
3755static void
3756s3_do16_push_pop (char *str)
3757{
3758 s3_skip_whitespace (str);
3759 if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
f9e53abc 3760 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3761 return;
3762}
3763
3764static void
3765s3_do16_rpush (char *str)
3766{
3767 int reg;
3768 int val;
3769 s3_skip_whitespace (str);
3770 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3771 || s3_skip_past_comma (&str) == (int) s3_FAIL
3772 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
f9e53abc 3773 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3774 return;
3775
3776 /* 0: indicate 32.
33eaf5de 3777 1: invalid value.
c3b7224a 3778 2: to 31: normal value. */
f9e53abc 3779 val = s3_inst.instruction & 0x1f;
c3b7224a
NC
3780 if (val == 1)
3781 {
f9e53abc
NC
3782 s3_inst.error = _("imm5 should >= 2");
3783 return;
c3b7224a
NC
3784 }
3785 if (reg >= 32)
3786 {
3787 s3_inst.error = _("reg should <= 31");
3788 return;
3789 }
3790}
3791
3792static void
3793s3_do16_rpop (char *str)
3794{
3795 int reg;
3796 int val;
3797 s3_skip_whitespace (str);
3798 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3799 || s3_skip_past_comma (&str) == (int) s3_FAIL
3800 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
f9e53abc 3801 || s3_end_of_line (str) == (int) s3_FAIL)
c3b7224a
NC
3802 return;
3803
3804 /* 0: indicate 32.
33eaf5de 3805 1: invalid value.
c3b7224a
NC
3806 2: to 31: normal value. */
3807 val = s3_inst.instruction & 0x1f;
3808 if (val == 1)
3809 {
3810 s3_inst.error = _("imm5 should >= 2");
3811 return;
3812 }
3813
3814 if (reg >= 32)
3815 {
3816 s3_inst.error = _("reg should <= 31");
3817 return;
3818 }
f9e53abc 3819 else
c3b7224a
NC
3820 {
3821 if ((reg + val) <= 32)
3822 reg = reg + val - 1;
3823 else
3824 reg = reg + val - 33;
3825 s3_inst.instruction &= 0x7c1f;
3826 s3_inst.instruction |= (reg << 5);
3827 return;
1c0d3aa6
NC
3828 }
3829}
3830
3831/* Handle lcb/lcw/lce/scb/scw/sce. */
3832static void
c3b7224a 3833s3_do_ldst_unalign (char *str)
1c0d3aa6
NC
3834{
3835 int conflict_reg;
3836
c3b7224a 3837 if (s3_university_version == 1)
1c0d3aa6 3838 {
c3b7224a 3839 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
1c0d3aa6
NC
3840 return;
3841 }
3842
c3b7224a 3843 s3_skip_whitespace (str);
1c0d3aa6
NC
3844
3845 /* lcb/scb [rA]+. */
3846 if (*str == '[')
3847 {
3848 str++;
c3b7224a 3849 s3_skip_whitespace (str);
1c0d3aa6 3850
c3b7224a 3851 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
1c0d3aa6
NC
3852 return;
3853
3854 if (*str++ == ']')
3855 {
3856 if (*str++ != '+')
3857 {
c3b7224a 3858 s3_inst.error = _("missing +");
1c0d3aa6
NC
3859 return;
3860 }
3861 }
3862 else
3863 {
c3b7224a 3864 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3865 return;
3866 }
3867
c3b7224a 3868 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3869 return;
3870 }
3871 /* lcw/lce/scb/sce rD, [rA]+. */
3872 else
3873 {
c3b7224a
NC
3874 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3875 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3876 {
3877 return;
3878 }
3879
c3b7224a 3880 s3_skip_whitespace (str);
1c0d3aa6
NC
3881 if (*str++ == '[')
3882 {
3883 int reg;
3884
c3b7224a
NC
3885 s3_skip_whitespace (str);
3886 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
3887 {
3888 return;
3889 }
3890
3891 /* Conflicts can occur on stores as well as loads. */
3892 conflict_reg = (conflict_reg == reg);
c3b7224a 3893 s3_skip_whitespace (str);
1c0d3aa6
NC
3894 if (*str++ == ']')
3895 {
c3b7224a 3896 unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
1c0d3aa6
NC
3897
3898 if (*str++ == '+')
3899 {
3900 if (conflict_reg)
3901 {
3902 as_warn (_("%s register same as write-back base"),
3903 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3904 ? _("destination") : _("source")));
3905 }
3906 }
3907 else
3908 {
c3b7224a 3909 s3_inst.error = _("missing +");
1c0d3aa6
NC
3910 return;
3911 }
3912
c3b7224a 3913 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
3914 return;
3915 }
3916 else
3917 {
c3b7224a 3918 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3919 return;
3920 }
3921 }
3922 else
3923 {
c3b7224a 3924 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3925 return;
3926 }
3927 }
3928}
3929
3930/* Handle alw/asw. */
3931static void
c3b7224a 3932s3_do_ldst_atomic (char *str)
1c0d3aa6 3933{
c3b7224a 3934 if (s3_university_version == 1)
1c0d3aa6 3935 {
c3b7224a 3936 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
1c0d3aa6
NC
3937 return;
3938 }
3939
c3b7224a 3940 s3_skip_whitespace (str);
1c0d3aa6 3941
c3b7224a
NC
3942 if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3943 || (s3_skip_past_comma (&str) == (int) s3_FAIL))
1c0d3aa6
NC
3944 {
3945 return;
3946 }
3947 else
3948 {
3949
c3b7224a 3950 s3_skip_whitespace (str);
1c0d3aa6
NC
3951 if (*str++ == '[')
3952 {
3953 int reg;
3954
c3b7224a
NC
3955 s3_skip_whitespace (str);
3956 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
3957 {
3958 return;
3959 }
3960
c3b7224a 3961 s3_skip_whitespace (str);
1c0d3aa6
NC
3962 if (*str++ != ']')
3963 {
c3b7224a 3964 s3_inst.error = _("missing ]");
1c0d3aa6
NC
3965 return;
3966 }
3967
c3b7224a 3968 s3_end_of_line (str);
1c0d3aa6
NC
3969 }
3970 else
c3b7224a 3971 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
3972 }
3973}
3974
3975static void
c3b7224a 3976s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
f9e53abc
NC
3977 struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
3978 symbolS *add_symbol)
1c0d3aa6
NC
3979{
3980 int i;
3981 char *p;
3982 fixS *fixp = NULL;
b3549761 3983 fixS *cur_fixp = NULL;
1c0d3aa6 3984 long where;
c3b7224a 3985 struct s3_score_it inst_main;
1c0d3aa6 3986
c3b7224a 3987 memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
1c0d3aa6
NC
3988
3989 /* Adjust instruction opcode and to be relaxed instruction opcode. */
c3b7224a 3990 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
1c0d3aa6
NC
3991 inst_main.type = Insn_PIC;
3992
3993 for (i = 0; i < var_num; i++)
3994 {
3995 inst_main.relax_size += var_insts[i].size;
c3b7224a 3996 var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
f9e53abc 3997 s3_GET_INSN_CLASS (var_insts[i].type));
1c0d3aa6
NC
3998 }
3999
4000 /* Check data dependency. */
c3b7224a 4001 s3_handle_dependency (&inst_main);
1c0d3aa6
NC
4002
4003 /* Start a new frag if frag_now is not empty. */
4004 if (frag_now_fix () != 0)
4005 {
4006 if (!frag_now->tc_frag_data.is_insn)
4007 {
4008 frag_wane (frag_now);
4009 }
4010 frag_new (0);
4011 }
4012 frag_grow (20);
4013
4014 /* Write fr_fix part. */
4015 p = frag_more (inst_main.size);
c3b7224a 4016 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
1c0d3aa6
NC
4017
4018 if (inst_main.reloc.type != BFD_RELOC_NONE)
c3b7224a 4019 fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
f9e53abc 4020 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
1c0d3aa6 4021
b3549761
NC
4022 frag_now->tc_frag_data.fixp = fixp;
4023 cur_fixp = frag_now->tc_frag_data.fixp;
1c0d3aa6
NC
4024
4025#ifdef OBJ_ELF
4026 dwarf2_emit_insn (inst_main.size);
4027#endif
4028
4029 where = p - frag_now->fr_literal + inst_main.size;
4030 for (i = 0; i < var_num; i++)
4031 {
4032 if (i > 0)
4033 where += var_insts[i - 1].size;
4034
4035 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4036 {
c3b7224a 4037 fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
f9e53abc
NC
4038 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4039 var_insts[i].reloc.type);
1c0d3aa6
NC
4040 if (fixp)
4041 {
b3549761
NC
4042 if (cur_fixp)
4043 {
4044 cur_fixp->fx_next = fixp;
4045 cur_fixp = cur_fixp->fx_next;
4046 }
4047 else
4048 {
4049 frag_now->tc_frag_data.fixp = fixp;
4050 cur_fixp = frag_now->tc_frag_data.fixp;
4051 }
1c0d3aa6
NC
4052 }
4053 }
4054 }
4055
c3b7224a
NC
4056 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4057 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
f9e53abc 4058 0, inst_main.size, 0), add_symbol, 0, NULL);
1c0d3aa6
NC
4059
4060 /* Write fr_var part.
c3b7224a 4061 no calling s3_gen_insn_frag, no fixS will be generated. */
1c0d3aa6
NC
4062 for (i = 0; i < var_num; i++)
4063 {
c3b7224a 4064 s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
1c0d3aa6
NC
4065 p += var_insts[i].size;
4066 }
4067 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4068 s3_inst.bwarn = -1;
1c0d3aa6
NC
4069}
4070
c3b7224a 4071/* Build a relax frag for la instruction when generating s3_PIC,
1c0d3aa6 4072 external symbol first and local symbol second. */
1c0d3aa6 4073static void
c3b7224a 4074s3_build_la_pic (int reg_rd, expressionS exp)
1c0d3aa6
NC
4075{
4076 symbolS *add_symbol = exp.X_add_symbol;
4077 offsetT add_number = exp.X_add_number;
c3b7224a
NC
4078 struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4079 struct s3_score_it var_insts[s3_RELAX_INST_NUM];
1c0d3aa6
NC
4080 int fix_num = 0;
4081 int var_num = 0;
c3b7224a 4082 char tmp[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6
NC
4083 int r1_bak;
4084
c3b7224a
NC
4085 r1_bak = s3_nor1;
4086 s3_nor1 = 0;
1c0d3aa6
NC
4087
4088 if (add_number == 0)
4089 {
4090 fix_num = 1;
4091 var_num = 2;
4092
f9e53abc 4093 /* For an external symbol, only one insn is generated;
8fce5f8c 4094 For a local symbol, two insns are generated. */
1c0d3aa6 4095 /* Fix part
8fce5f8c 4096 For an external symbol: lw rD, <sym>($gp)
f9e53abc 4097 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
8d1015a8 4098 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
c3b7224a 4099 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4100 return;
4101
c3b7224a
NC
4102 if (reg_rd == s3_PIC_CALL_REG)
4103 s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4104 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4105
4106 /* Var part
4107 For a local symbol :
4108 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4109 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
c3b7224a
NC
4110 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4111 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
8d1015a8 4112 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
c3b7224a 4113 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4114 return;
4115
c3b7224a
NC
4116 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4117 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
1c0d3aa6
NC
4118 }
4119 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4120 {
4121 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
8d1015a8 4122 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
c3b7224a 4123 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4124 return;
4125
4126 /* Insn 2 */
4127 fix_num = 1;
4128 var_num = 1;
4129 /* Fix part
4130 For an external symbol: addi rD, <constant> */
48903831 4131 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
c3b7224a 4132 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4133 return;
4134
c3b7224a 4135 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4136
4137 /* Var part
4138 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
8d1015a8
AM
4139 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd,
4140 S_GET_NAME (add_symbol), (int) add_number);
c3b7224a 4141 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4142 return;
4143
c3b7224a
NC
4144 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4145 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
1c0d3aa6
NC
4146 }
4147 else
4148 {
4149 int hi = (add_number >> 16) & 0x0000FFFF;
4150 int lo = add_number & 0x0000FFFF;
4151
4152 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
8d1015a8 4153 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
c3b7224a 4154 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4155 return;
4156
4157 /* Insn 2 */
4158 fix_num = 1;
4159 var_num = 1;
4160 /* Fix part
4161 For an external symbol: ldis r1, HI%<constant> */
48903831 4162 sprintf (tmp, "ldis r1, %d", hi);
c3b7224a 4163 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4164 return;
4165
c3b7224a 4166 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4167
4168 /* Var part
4169 For a local symbol: ldis r1, HI%<constant>
33eaf5de 4170 but, if lo is out of 16 bit, make hi plus 1 */
1c0d3aa6
NC
4171 if ((lo < -0x8000) || (lo > 0x7fff))
4172 {
4173 hi += 1;
4174 }
48903831 4175 sprintf (tmp, "ldis_pic r1, %d", hi);
c3b7224a 4176 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4177 return;
4178
c3b7224a
NC
4179 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4180 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
1c0d3aa6
NC
4181
4182 /* Insn 3 */
4183 fix_num = 1;
4184 var_num = 1;
4185 /* Fix part
4186 For an external symbol: ori r1, LO%<constant> */
48903831 4187 sprintf (tmp, "ori r1, %d", lo);
c3b7224a 4188 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4189 return;
4190
c3b7224a 4191 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4192
4193 /* Var part
4194 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
8d1015a8 4195 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo);
c3b7224a 4196 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
4197 return;
4198
c3b7224a
NC
4199 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4200 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
1c0d3aa6
NC
4201
4202 /* Insn 4: add rD, rD, r1 */
48903831 4203 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
c3b7224a 4204 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4205 return;
4206
f9e53abc
NC
4207 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4208 s3_inst.bwarn = -1;
1c0d3aa6
NC
4209 }
4210
c3b7224a 4211 s3_nor1 = r1_bak;
1c0d3aa6
NC
4212}
4213
4214/* Handle la. */
4215static void
c3b7224a 4216s3_do_macro_la_rdi32 (char *str)
1c0d3aa6
NC
4217{
4218 int reg_rd;
4219
c3b7224a
NC
4220 s3_skip_whitespace (str);
4221 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4222 || s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6
NC
4223 {
4224 return;
4225 }
4226 else
4227 {
c3b7224a 4228 /* Save str. */
1c0d3aa6 4229 char *keep_data = str;
c3b7224a
NC
4230 char append_str[s3_MAX_LITERAL_POOL_SIZE];
4231
4232 /* Check immediate value. */
4233 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4234 {
4235 s3_inst.error = _("expression error");
4236 return;
4237 }
4238 else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4239 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL))
4240 {
4241 s3_inst.error = _("value not in range [0, 0xffffffff]");
4242 return;
4243 }
4244
4245 /* Reset str. */
4246 str = keep_data;
1c0d3aa6
NC
4247
4248 /* la rd, simm16. */
c3b7224a 4249 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
1c0d3aa6 4250 {
c3b7224a 4251 s3_end_of_line (str);
1c0d3aa6
NC
4252 return;
4253 }
4254 /* la rd, imm32 or la rd, label. */
4255 else
4256 {
c3b7224a
NC
4257 s3_SET_INSN_ERROR (NULL);
4258 /* Reset str. */
1c0d3aa6 4259 str = keep_data;
c3b7224a
NC
4260 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4261 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
4262 {
4263 return;
4264 }
4265 else
4266 {
c3b7224a 4267 if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol))
14119072 4268 {
48903831 4269 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
c3b7224a 4270 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4271 return;
4272
48903831 4273 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
c3b7224a 4274 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4275 return;
4276 }
4277 else
4278 {
9c2799c2 4279 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a 4280 s3_build_la_pic (reg_rd, s3_inst.reloc.exp);
1c0d3aa6
NC
4281 }
4282
4283 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4284 s3_inst.bwarn = -1;
1c0d3aa6
NC
4285 }
4286 }
4287 }
4288}
4289
4290/* Handle li. */
4291static void
c3b7224a
NC
4292s3_do_macro_li_rdi32 (char *str)
4293{
1c0d3aa6
NC
4294
4295 int reg_rd;
4296
c3b7224a
NC
4297 s3_skip_whitespace (str);
4298 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4299 || s3_skip_past_comma (&str) == (int) s3_FAIL)
1c0d3aa6
NC
4300 {
4301 return;
4302 }
4303 else
4304 {
c3b7224a 4305 /* Save str. */
1c0d3aa6
NC
4306 char *keep_data = str;
4307
c3b7224a
NC
4308 /* Check immediate value. */
4309 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4310 {
4311 s3_inst.error = _("expression error");
4312 return;
4313 }
4314 else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL
4315 && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4316 {
4317 s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4318 return;
4319 }
4320
4321 /* Reset str. */
4322 str = keep_data;
4323
1c0d3aa6 4324 /* li rd, simm16. */
c3b7224a 4325 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
1c0d3aa6 4326 {
c3b7224a 4327 s3_end_of_line (str);
1c0d3aa6
NC
4328 return;
4329 }
4330 /* li rd, imm32. */
4331 else
4332 {
c3b7224a 4333 char append_str[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4334
c3b7224a 4335 /* Reset str. */
1c0d3aa6
NC
4336 str = keep_data;
4337
c3b7224a
NC
4338 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4339 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
4340 {
4341 return;
4342 }
c3b7224a 4343 else if (s3_inst.reloc.exp.X_add_symbol)
1c0d3aa6 4344 {
c3b7224a 4345 s3_inst.error = _("li rd label isn't correct instruction form");
1c0d3aa6
NC
4346 return;
4347 }
4348 else
4349 {
48903831 4350 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
1c0d3aa6 4351
c3b7224a 4352 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4353 return;
4354 else
4355 {
48903831 4356 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
c3b7224a 4357 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4358 return;
4359
4360 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4361 s3_inst.bwarn = -1;
1c0d3aa6
NC
4362 }
4363 }
4364 }
4365 }
4366}
4367
4368/* Handle mul/mulu/div/divu/rem/remu. */
4369static void
c3b7224a 4370s3_do_macro_mul_rdrsrs (char *str)
1c0d3aa6
NC
4371{
4372 int reg_rd;
4373 int reg_rs1;
4374 int reg_rs2;
4375 char *backupstr;
c3b7224a 4376 char append_str[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4377
c3b7224a
NC
4378 if (s3_university_version == 1)
4379 as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV);
1c0d3aa6
NC
4380
4381 strcpy (append_str, str);
4382 backupstr = append_str;
c3b7224a
NC
4383 s3_skip_whitespace (backupstr);
4384 if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4385 || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4386 || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL))
1c0d3aa6 4387 {
c3b7224a 4388 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
4389 return;
4390 }
4391
c3b7224a 4392 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
1c0d3aa6
NC
4393 {
4394 /* rem/remu rA, rB is error format. */
c3b7224a 4395 if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0)
1c0d3aa6 4396 {
c3b7224a 4397 s3_SET_INSN_ERROR (s3_BAD_ARGS);
1c0d3aa6
NC
4398 }
4399 else
4400 {
c3b7224a
NC
4401 s3_SET_INSN_ERROR (NULL);
4402 s3_do_rsrs (str);
1c0d3aa6
NC
4403 }
4404 return;
4405 }
4406 else
4407 {
c3b7224a
NC
4408 s3_SET_INSN_ERROR (NULL);
4409 if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4410 || (s3_end_of_line (backupstr) == (int) s3_FAIL))
1c0d3aa6
NC
4411 {
4412 return;
4413 }
4414 else
4415 {
c3b7224a 4416 char append_str1[s3_MAX_LITERAL_POOL_SIZE];
1c0d3aa6 4417
c3b7224a 4418 if (strcmp (s3_inst.name, "rem") == 0)
1c0d3aa6 4419 {
48903831
NC
4420 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4421 sprintf (append_str1, "mfceh r%d", reg_rd);
1c0d3aa6 4422 }
c3b7224a 4423 else if (strcmp (s3_inst.name, "remu") == 0)
1c0d3aa6 4424 {
48903831
NC
4425 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4426 sprintf (append_str1, "mfceh r%d", reg_rd);
1c0d3aa6
NC
4427 }
4428 else
4429 {
c3b7224a 4430 sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2);
48903831 4431 sprintf (append_str1, "mfcel r%d", reg_rd);
1c0d3aa6
NC
4432 }
4433
4434 /* Output mul/mulu or div/divu or rem/remu. */
c3b7224a 4435 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4436 return;
4437
4438 /* Output mfcel or mfceh. */
c3b7224a 4439 if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL)
1c0d3aa6
NC
4440 return;
4441
4442 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4443 s3_inst.bwarn = -1;
1c0d3aa6
NC
4444 }
4445 }
4446}
4447
4448static void
c3b7224a 4449s3_exp_macro_ldst_abs (char *str)
1c0d3aa6
NC
4450{
4451 int reg_rd;
4452 char *backupstr, *tmp;
c3b7224a
NC
4453 char append_str[s3_MAX_LITERAL_POOL_SIZE];
4454 char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4455 struct s3_score_it inst_backup;
1c0d3aa6
NC
4456 int r1_bak = 0;
4457
c3b7224a
NC
4458 r1_bak = s3_nor1;
4459 s3_nor1 = 0;
4460 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4461
4462 strcpy (verifystr, str);
4463 backupstr = verifystr;
c3b7224a
NC
4464 s3_skip_whitespace (backupstr);
4465 if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
4466 return;
4467
4468 tmp = backupstr;
c3b7224a 4469 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
1c0d3aa6
NC
4470 return;
4471
4472 backupstr = tmp;
48903831 4473 sprintf (append_str, "li r1 %s", backupstr);
c3b7224a 4474 s3_append_insn (append_str, TRUE);
1c0d3aa6 4475
c3b7224a 4476 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
48903831 4477 sprintf (append_str, " r%d, [r1,0]", reg_rd);
c3b7224a 4478 s3_do_ldst_insn (append_str);
1c0d3aa6 4479
c3b7224a 4480 s3_nor1 = r1_bak;
1c0d3aa6 4481}
f9e53abc 4482
c3b7224a
NC
4483/* Handle bcmpeq / bcmpne */
4484static void
4485s3_do_macro_bcmp (char *str)
1c0d3aa6 4486{
c3b7224a 4487 int reg_a , reg_b;
861d8651
AM
4488 char *keep_data;
4489 size_t keep_data_size;
4490 int i;
c3b7224a 4491 struct s3_score_it inst_expand[2];
02fb2970 4492 struct s3_score_it inst_main;
c3b7224a 4493
f9e53abc 4494 memset (inst_expand, 0, sizeof inst_expand);
c3b7224a
NC
4495 s3_skip_whitespace (str);
4496 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4497 || s3_skip_past_comma (&str) == (int) s3_FAIL
4498 ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4499 || s3_skip_past_comma (&str) == (int) s3_FAIL)
f9e53abc 4500 return;
861d8651
AM
4501
4502 keep_data_size = strlen (str) + 1;
4503 keep_data = xmalloc (keep_data_size * 2 + 14);
4504 memcpy (keep_data, str, keep_data_size);
4505
f9e53abc
NC
4506 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4507 ||reg_b == 0
c3b7224a 4508 || s3_end_of_line (str) == (int) s3_FAIL)
861d8651 4509 goto out;
c3b7224a
NC
4510 else if (s3_inst.reloc.exp.X_add_symbol == 0)
4511 {
4512 s3_inst.error = _("lacking label ");
861d8651 4513 goto out;
c3b7224a
NC
4514 }
4515 else
1c0d3aa6 4516 {
861d8651 4517 char *append_str = keep_data + keep_data_size;
c3b7224a 4518 s3_SET_INSN_ERROR (NULL);
f9e53abc 4519
c3b7224a
NC
4520 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
4521 s3_inst.reloc.pc_rel = 1;
4522 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
1c0d3aa6 4523
c3b7224a 4524 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
f9e53abc
NC
4525 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1)
4526 | ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7
4527 | ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20;
c3b7224a
NC
4528
4529 /* Check and set offset. */
4530 if (((val & 0xfffffe00) != 0)
f9e53abc 4531 && ((val & 0xfffffe00) != 0xfffffe00))
1c0d3aa6 4532 {
c3b7224a
NC
4533 /* support bcmp --> cmp!+beq (bne) */
4534 if (s3_score_pic == s3_NO_PIC)
4535 {
861d8651
AM
4536 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
4537 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4538 goto out;
4539 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4540 memcpy (append_str, "beq ", 4);
861d8651 4541 else
a05e3e20
L
4542 memcpy (append_str, "bne ", 4);
4543 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
861d8651
AM
4544 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4545 goto out;
f9e53abc
NC
4546 }
4547 else
4548 {
4549 gas_assert (s3_inst.reloc.exp.X_add_symbol);
4550 }
4551 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4552 s3_inst.bwarn = -1;
861d8651 4553 goto out;
1c0d3aa6 4554 }
c3b7224a 4555 else
1c0d3aa6 4556 {
c3b7224a
NC
4557 val >>= 1;
4558 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
4559 | (((val >> 1) & 0x7) << 7)
4560 | (((val >> 4) & 0x1f) << 20);
1c0d3aa6
NC
4561 }
4562
c3b7224a
NC
4563 /* Backup s3_inst. */
4564 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6 4565
f9e53abc 4566 if (s3_score_pic == s3_NO_PIC)
c3b7224a 4567 {
861d8651
AM
4568 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b);
4569 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4570 goto out;
4571 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
f9e53abc 4572
861d8651 4573 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4574 memcpy (append_str, "beq ", 4);
861d8651 4575 else
a05e3e20
L
4576 memcpy (append_str, "bne ", 4);
4577 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
861d8651
AM
4578 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4579 goto out;
4580 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
c3b7224a
NC
4581 }
4582 else
4583 {
9c2799c2 4584 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
4585 }
4586 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4587 inst_main.type = Insn_BCMP;
1c0d3aa6 4588
c3b7224a
NC
4589 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4590 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
1c0d3aa6 4591
c3b7224a 4592 for (i = 0; i < 2; i++)
f9e53abc 4593 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
c3b7224a
NC
4594 s3_GET_INSN_CLASS (inst_expand[i].type));
4595 /* Check data dependency. */
4596 s3_handle_dependency (&inst_main);
4597 /* Start a new frag if frag_now is not empty. */
4598 if (frag_now_fix () != 0)
f9e53abc
NC
4599 {
4600 if (!frag_now->tc_frag_data.is_insn)
4601 frag_wane (frag_now);
4602 frag_new (0);
4603 }
c3b7224a 4604 frag_grow (20);
1c0d3aa6 4605
c3b7224a
NC
4606 /* Write fr_fix part. */
4607 char *p;
4608 p = frag_more (inst_main.size);
4609 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
1c0d3aa6 4610
c3b7224a 4611 if (inst_main.reloc.type != BFD_RELOC_NONE)
f9e53abc
NC
4612 {
4613 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4614 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4615 }
c3b7224a
NC
4616#ifdef OBJ_ELF
4617 dwarf2_emit_insn (inst_main.size);
4618#endif
1c0d3aa6 4619
c3b7224a
NC
4620 /* s3_GP instruction can not do optimization, only can do relax between
4621 1 instruction and 3 instructions. */
4622 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4623 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4624 inst_main.reloc.exp.X_add_symbol, 0, NULL);
1c0d3aa6 4625
c3b7224a
NC
4626 /* Write fr_var part.
4627 no calling s3_gen_insn_frag, no fixS will be generated. */
4628 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4629 p += inst_expand[0].size;
4630 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4631 p += inst_expand[1].size;
1c0d3aa6 4632
8fce5f8c 4633 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 4634 s3_inst.bwarn = -1;
f9e53abc 4635 }
861d8651
AM
4636 out:
4637 free (keep_data);
c3b7224a
NC
4638}
4639
4640/* Handle bcmpeqz / bcmpnez */
4641static void
4642s3_do_macro_bcmpz (char *str)
4643{
f9e53abc 4644 int reg_a;
861d8651
AM
4645 char *keep_data;
4646 size_t keep_data_size;
4647 int i;
c3b7224a
NC
4648 struct s3_score_it inst_expand[2];
4649 struct s3_score_it inst_main;
4650
f9e53abc 4651 memset (inst_expand, 0, sizeof inst_expand);
c3b7224a
NC
4652 s3_skip_whitespace (str);
4653 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
f9e53abc 4654 || s3_skip_past_comma (&str) == (int) s3_FAIL)
c3b7224a 4655 return;
c3b7224a 4656
861d8651
AM
4657 keep_data_size = strlen (str) + 1;
4658 keep_data = xmalloc (keep_data_size * 2 + 13);
4659 memcpy (keep_data, str, keep_data_size);
f9e53abc
NC
4660
4661 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4662 || s3_end_of_line (str) == (int) s3_FAIL)
861d8651 4663 goto out;
c3b7224a
NC
4664 else if (s3_inst.reloc.exp.X_add_symbol == 0)
4665 {
4666 s3_inst.error = _("lacking label ");
861d8651 4667 goto out;
c3b7224a
NC
4668 }
4669 else
4670 {
861d8651 4671 char *append_str = keep_data + keep_data_size;
c3b7224a
NC
4672 s3_SET_INSN_ERROR (NULL);
4673 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
f9e53abc 4674 s3_inst.reloc.pc_rel = 1;
c3b7224a
NC
4675 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
4676
4677 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
f9e53abc 4678 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
4679
4680 /* Check and set offset. */
4681 if (((val & 0xfffffe00) != 0)
f9e53abc 4682 && ((val & 0xfffffe00) != 0xfffffe00))
c3b7224a
NC
4683 {
4684 if (s3_score_pic == s3_NO_PIC)
4685 {
861d8651
AM
4686 sprintf (append_str, "cmpi! r%d, 0", reg_a);
4687 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4688 goto out;
4689 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4690 memcpy (append_str, "beq ", 4);
861d8651 4691 else
a05e3e20
L
4692 memcpy (append_str, "bne ", 4);
4693 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
861d8651
AM
4694 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4695 goto out;
c3b7224a
NC
4696 }
4697 else
4698 {
9c2799c2 4699 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
4700 }
4701 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4702 s3_inst.bwarn = -1;
861d8651 4703 goto out;
c3b7224a
NC
4704 }
4705 else
4706 {
4707 val >>= 1;
4708 s3_inst.instruction |= (val & 0x1)
f9e53abc
NC
4709 | (((val >> 1) & 0x7) << 7)
4710 | (((val >> 4) & 0x1f) << 20);
c3b7224a
NC
4711 }
4712
4713 /* Backup s3_inst. */
4714 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
f9e53abc
NC
4715
4716 if (s3_score_pic == s3_NO_PIC)
c3b7224a 4717 {
861d8651
AM
4718 sprintf (append_str, "cmpi! r%d, 0", reg_a);
4719 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4720 goto out;
4721 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4722 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
a05e3e20 4723 memcpy (append_str, "beq ", 4);
861d8651 4724 else
a05e3e20
L
4725 memcpy (append_str, "bne ", 4);
4726 memmove (append_str + 4, keep_data, strlen (keep_data) + 1);
861d8651
AM
4727 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL)
4728 goto out;
4729 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
c3b7224a
NC
4730 }
4731 else
4732 {
9c2799c2 4733 gas_assert (s3_inst.reloc.exp.X_add_symbol);
c3b7224a
NC
4734 }
4735 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4736 inst_main.type = Insn_BCMP;
4737
4738 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4739 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4740
4741 for (i = 0; i < 2; i++)
f9e53abc
NC
4742 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction ,
4743 s3_GET_INSN_CLASS (inst_expand[i].type));
c3b7224a
NC
4744 /* Check data dependency. */
4745 s3_handle_dependency (&inst_main);
4746 /* Start a new frag if frag_now is not empty. */
4747 if (frag_now_fix () != 0)
f9e53abc
NC
4748 {
4749 if (!frag_now->tc_frag_data.is_insn)
4750 frag_wane (frag_now);
4751 frag_new (0);
4752 }
c3b7224a
NC
4753 frag_grow (20);
4754
4755 /* Write fr_fix part. */
4756 char *p;
4757 p = frag_more (inst_main.size);
4758 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4759
4760 if (inst_main.reloc.type != BFD_RELOC_NONE)
f9e53abc
NC
4761 {
4762 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4763 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4764 }
c3b7224a
NC
4765#ifdef OBJ_ELF
4766 dwarf2_emit_insn (inst_main.size);
4767#endif
4768
4769 /* s3_GP instruction can not do optimization, only can do relax between
4770 1 instruction and 3 instructions. */
4771 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4772 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4773 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4774
4775 /* Write fr_var part.
4776 no calling s3_gen_insn_frag, no fixS will be generated. */
4777 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4778 p += inst_expand[0].size;
4779 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4780 p += inst_expand[1].size;
4781
4782 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4783 s3_inst.bwarn = -1;
f9e53abc 4784 }
861d8651
AM
4785 out:
4786 free (keep_data);
c3b7224a
NC
4787}
4788
4789static int
4790s3_nopic_need_relax (symbolS * sym, int before_relaxing)
4791{
4792 if (sym == NULL)
4793 return 0;
4794 else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0)
4795 {
4796 const char *symname;
4797 const char *segname;
4798
4799 /* Find out whether this symbol can be referenced off the $gp
4800 register. It can be if it is smaller than the -G size or if
4801 it is in the .sdata or .sbss section. Certain symbols can
4802 not be referenced off the $gp, although it appears as though
4803 they can. */
4804 symname = S_GET_NAME (sym);
4805 if (symname != (const char *)NULL
4806 && (strcmp (symname, "eprol") == 0
4807 || strcmp (symname, "etext") == 0
4808 || strcmp (symname, "_gp") == 0
4809 || strcmp (symname, "edata") == 0
4810 || strcmp (symname, "_fbss") == 0
4811 || strcmp (symname, "_fdata") == 0
4812 || strcmp (symname, "_ftext") == 0
4813 || strcmp (symname, "end") == 0
4814 || strcmp (symname, GP_DISP_LABEL) == 0))
4815 {
4816 return 1;
4817 }
4818 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
f9e53abc
NC
4819 /* We must defer this decision until after the whole file has been read,
4820 since there might be a .extern after the first use of this symbol. */
4821 || (before_relaxing
4822 && S_GET_VALUE (sym) == 0)
4823 || (S_GET_VALUE (sym) != 0
4824 && S_GET_VALUE (sym) <= s3_g_switch_value)))
c3b7224a
NC
4825 {
4826 return 0;
4827 }
4828
4829 segname = segment_name (S_GET_SEGMENT (sym));
4830 return (strcmp (segname, ".sdata") != 0
4831 && strcmp (segname, ".sbss") != 0
4832 && strncmp (segname, ".sdata.", 7) != 0
4833 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4834 }
4835 /* We are not optimizing for the $gp register. */
4836 else
4837 return 1;
4838}
4839
4840/* Build a relax frag for lw/st instruction when generating s3_PIC,
4841 external symbol first and local symbol second. */
4842static void
4843s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4844{
4845 symbolS *add_symbol = exp.X_add_symbol;
4846 int add_number = exp.X_add_number;
4847 struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4848 struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4849 int fix_num = 0;
4850 int var_num = 0;
4851 char tmp[s3_MAX_LITERAL_POOL_SIZE];
4852 int r1_bak;
4853
4854 r1_bak = s3_nor1;
4855 s3_nor1 = 0;
4856
4857 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4858 {
4859 fix_num = 1;
4860 var_num = 2;
4861
4862 /* For an external symbol, two insns are generated;
4863 For a local symbol, three insns are generated. */
4864 /* Fix part
4865 For an external symbol: lw rD, <sym>($gp)
f9e53abc 4866 (BFD_RELOC_SCORE_GOT15) */
8d1015a8 4867 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol));
c3b7224a
NC
4868 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4869 return;
4870
4871 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4872
4873 /* Var part
4874 For a local symbol :
4875 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4876 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4877 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4878 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
8d1015a8 4879 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol));
c3b7224a
NC
4880 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4881 return;
4882
4883 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4884 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4885
4886 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4887 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4888 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4889 return;
4890
4891 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4892 s3_inst.bwarn = -1;
4893 }
4894 else
4895 {
4896 s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)");
8fce5f8c 4897 return;
1c0d3aa6
NC
4898 }
4899
c3b7224a 4900 s3_nor1 = r1_bak;
1c0d3aa6
NC
4901}
4902
4903static void
c3b7224a 4904s3_do_macro_ldst_label (char *str)
1c0d3aa6
NC
4905{
4906 int i;
4907 int ldst_gp_p = 0;
4908 int reg_rd;
4909 int r1_bak;
4910 char *backup_str;
4911 char *label_str;
4912 char *absolute_value;
c3b7224a
NC
4913 char append_str[3][s3_MAX_LITERAL_POOL_SIZE];
4914 char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4915 struct s3_score_it inst_backup;
4916 struct s3_score_it inst_expand[3];
4917 struct s3_score_it inst_main;
1c0d3aa6 4918
c3b7224a 4919 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
4920 strcpy (verifystr, str);
4921 backup_str = verifystr;
4922
c3b7224a
NC
4923 s3_skip_whitespace (backup_str);
4924 if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
1c0d3aa6
NC
4925 return;
4926
c3b7224a 4927 if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL)
1c0d3aa6
NC
4928 return;
4929
4930 label_str = backup_str;
4931
4932 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4933 if (*backup_str == '[')
4934 {
c3b7224a
NC
4935 s3_inst.type = Rd_rvalueRs_preSI12;
4936 s3_do_ldst_insn (str);
1c0d3aa6
NC
4937 return;
4938 }
4939
4940 /* Ld/st rD, imm. */
4941 absolute_value = backup_str;
c3b7224a
NC
4942 s3_inst.type = Rd_rvalueRs_SI15;
4943
4944 if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL)
4945 {
4946 s3_inst.error = _("expression error");
4947 return;
4948 }
4949 else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4950 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL))
4951 {
4952 s3_inst.error = _("value not in range [0, 0x7fffffff]");
4953 return;
4954 }
4955 else if (s3_end_of_line (backup_str) == (int) s3_FAIL)
1c0d3aa6 4956 {
c3b7224a 4957 s3_inst.error = _("end on line error");
1c0d3aa6
NC
4958 return;
4959 }
4960 else
4961 {
c3b7224a 4962 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 4963 {
c3b7224a
NC
4964 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4965 s3_exp_macro_ldst_abs (str);
1c0d3aa6
NC
4966 return;
4967 }
4968 }
4969
4970 /* Ld/st rD, label. */
c3b7224a 4971 s3_inst.type = Rd_rvalueRs_SI15;
1c0d3aa6 4972 backup_str = absolute_value;
c3b7224a
NC
4973 if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL)
4974 || (s3_end_of_line (backup_str) == (int) s3_FAIL))
1c0d3aa6
NC
4975 {
4976 return;
4977 }
4978 else
4979 {
c3b7224a 4980 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 4981 {
c3b7224a
NC
4982 if (!s3_inst.error)
4983 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
4984
4985 return;
4986 }
4987
c3b7224a 4988 if (s3_score_pic == s3_PIC)
1c0d3aa6 4989 {
8fce5f8c 4990 int ldst_idx = 0;
c3b7224a 4991 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
d3ce72d0
NC
4992 s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp,
4993 s3_score_ldst_insns[ldst_idx * 3 + 0].template_name);
8fce5f8c 4994 return;
1c0d3aa6
NC
4995 }
4996 else
4997 {
c3b7224a 4998 if ((s3_inst.reloc.exp.X_add_number <= 0x3fff)
f9e53abc
NC
4999 && (s3_inst.reloc.exp.X_add_number >= -0x4000)
5000 && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1)))
1c0d3aa6
NC
5001 {
5002 int ldst_idx = 0;
5003
5004 /* Assign the real opcode. */
c3b7224a
NC
5005 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
5006 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
5007 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value;
5008 s3_inst.instruction |= reg_rd << 20;
5009 s3_inst.instruction |= s3_GP << 15;
5010 s3_inst.relax_inst = 0x8000;
5011 s3_inst.relax_size = 0;
1c0d3aa6
NC
5012 ldst_gp_p = 1;
5013 }
5014 }
5015 }
5016
c3b7224a
NC
5017 /* Backup s3_inst. */
5018 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
5019 r1_bak = s3_nor1;
5020 s3_nor1 = 0;
1c0d3aa6
NC
5021
5022 /* Determine which instructions should be output. */
48903831
NC
5023 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
5024 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
5025 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
1c0d3aa6
NC
5026
5027 /* Generate three instructions.
5028 la r1, label
5029 ld/st rd, [r1, 0] */
5030 for (i = 0; i < 3; i++)
5031 {
c3b7224a 5032 if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL)
1c0d3aa6
NC
5033 return;
5034
c3b7224a 5035 memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it));
1c0d3aa6
NC
5036 }
5037
5038 if (ldst_gp_p)
5039 {
5040 char *p;
5041
5042 /* Adjust instruction opcode and to be relaxed instruction opcode. */
c3b7224a
NC
5043 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
5044
f9e53abc
NC
5045 /* relax lw rd, label -> ldis rs, imm16
5046 ori rd, imm16
5047 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
c3b7224a
NC
5048 if (inst_expand[2].relax_size == 0)
5049 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
5050 else
5051 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size;
5052
1c0d3aa6
NC
5053 inst_main.type = Insn_GP;
5054
5055 for (i = 0; i < 3; i++)
f9e53abc 5056 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
c3b7224a 5057 s3_GET_INSN_CLASS (inst_expand[i].type));
1c0d3aa6
NC
5058
5059 /* Check data dependency. */
c3b7224a 5060 s3_handle_dependency (&inst_main);
1c0d3aa6
NC
5061
5062 /* Start a new frag if frag_now is not empty. */
5063 if (frag_now_fix () != 0)
5064 {
5065 if (!frag_now->tc_frag_data.is_insn)
5066 frag_wane (frag_now);
5067
5068 frag_new (0);
5069 }
5070 frag_grow (20);
5071
5072 /* Write fr_fix part. */
5073 p = frag_more (inst_main.size);
c3b7224a 5074 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
1c0d3aa6
NC
5075
5076 if (inst_main.reloc.type != BFD_RELOC_NONE)
5077 {
c3b7224a 5078 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
f9e53abc 5079 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
1c0d3aa6
NC
5080 }
5081
5082#ifdef OBJ_ELF
5083 dwarf2_emit_insn (inst_main.size);
5084#endif
5085
c3b7224a 5086 /* s3_GP instruction can not do optimization, only can do relax between
1c0d3aa6 5087 1 instruction and 3 instructions. */
c3b7224a
NC
5088 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
5089 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
1c0d3aa6
NC
5090 inst_main.reloc.exp.X_add_symbol, 0, NULL);
5091
5092 /* Write fr_var part.
c3b7224a
NC
5093 no calling s3_gen_insn_frag, no fixS will be generated. */
5094 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
1c0d3aa6 5095 p += inst_expand[0].size;
c3b7224a 5096 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
1c0d3aa6 5097 p += inst_expand[1].size;
c3b7224a 5098
f9e53abc
NC
5099 /* relax lw rd, label -> ldis rs, imm16
5100 ori rd, imm16
5101 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
c3b7224a
NC
5102 if (inst_expand[2].relax_size == 0)
5103 s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
5104 else
5105 s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size);
1c0d3aa6
NC
5106 }
5107 else
5108 {
c3b7224a
NC
5109 s3_gen_insn_frag (&inst_expand[0], NULL);
5110 s3_gen_insn_frag (&inst_expand[1], NULL);
5111 s3_gen_insn_frag (&inst_expand[2], NULL);
1c0d3aa6 5112 }
c3b7224a 5113 s3_nor1 = r1_bak;
1c0d3aa6
NC
5114
5115 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
c3b7224a 5116 s3_inst.bwarn = -1;
1c0d3aa6
NC
5117}
5118
5119static void
c3b7224a 5120s3_do_lw_pic (char *str)
1c0d3aa6
NC
5121{
5122 int reg_rd;
5123
c3b7224a
NC
5124 s3_skip_whitespace (str);
5125 if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5126 || (s3_skip_past_comma (&str) == (int) s3_FAIL)
5127 || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
5128 || (s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
5129 {
5130 return;
5131 }
5132 else
5133 {
c3b7224a 5134 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5135 {
c3b7224a
NC
5136 if (!s3_inst.error)
5137 s3_inst.error = s3_BAD_ARGS;
1c0d3aa6
NC
5138
5139 return;
5140 }
5141
c3b7224a
NC
5142 s3_inst.instruction |= s3_GP << 15;
5143 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
1c0d3aa6
NC
5144 }
5145}
5146
5147static void
c3b7224a 5148s3_do_empty (char *str)
1c0d3aa6
NC
5149{
5150 str = str;
c3b7224a 5151 if (s3_university_version == 1)
1c0d3aa6 5152 {
c3b7224a
NC
5153 if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004)
5154 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024)
5155 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044)
5156 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064))
1c0d3aa6 5157 {
c3b7224a 5158 s3_inst.error = s3_ERR_FOR_SCORE5U_MMU;
1c0d3aa6
NC
5159 return;
5160 }
5161 }
c3b7224a 5162 if (s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
5163 return;
5164
c3b7224a 5165 if (s3_inst.relax_inst != 0x8000)
1c0d3aa6 5166 {
c3b7224a 5167 if (s3_inst.type == NO_OPD)
1c0d3aa6 5168 {
c3b7224a 5169 s3_inst.relax_size = 2;
1c0d3aa6
NC
5170 }
5171 else
5172 {
c3b7224a 5173 s3_inst.relax_size = 4;
1c0d3aa6
NC
5174 }
5175 }
5176}
5177
5178static void
c3b7224a
NC
5179s3_do16_int (char *str)
5180{
5181 s3_skip_whitespace (str);
5182 return;
5183}
5184
5185static void
5186s3_do_jump (char *str)
1c0d3aa6
NC
5187{
5188 char *save_in;
1c0d3aa6 5189
c3b7224a
NC
5190 s3_skip_whitespace (str);
5191 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5192 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
5193 return;
5194
c3b7224a 5195 if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5196 {
c3b7224a 5197 s3_inst.error = _("lacking label ");
1c0d3aa6
NC
5198 return;
5199 }
5200
c3b7224a 5201 if (!(s3_inst.reloc.exp.X_add_number >= -16777216
f9e53abc 5202 && s3_inst.reloc.exp.X_add_number <= 16777215))
1c0d3aa6 5203 {
c3b7224a 5204 s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
1c0d3aa6
NC
5205 return;
5206 }
5207
5208 save_in = input_line_pointer;
5209 input_line_pointer = str;
c3b7224a
NC
5210 s3_inst.reloc.type = BFD_RELOC_SCORE_JMP;
5211 s3_inst.reloc.pc_rel = 1;
1c0d3aa6
NC
5212 input_line_pointer = save_in;
5213}
5214
5215static void
c3b7224a 5216s3_do_branch (char *str)
1c0d3aa6 5217{
c3b7224a
NC
5218 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5219 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6
NC
5220 {
5221 return;
5222 }
c3b7224a 5223 else if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5224 {
c3b7224a 5225 s3_inst.error = _("lacking label ");
1c0d3aa6
NC
5226 return;
5227 }
c3b7224a 5228 else if (!(s3_inst.reloc.exp.X_add_number >= -524288
f9e53abc 5229 && s3_inst.reloc.exp.X_add_number <= 524287))
1c0d3aa6 5230 {
33eaf5de 5231 s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19-1");
1c0d3aa6
NC
5232 return;
5233 }
5234
c3b7224a
NC
5235 s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5236 s3_inst.reloc.pc_rel = 1;
1c0d3aa6
NC
5237
5238 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
c3b7224a 5239 s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5);
1c0d3aa6 5240
41c55c87 5241 /* Compute 16 bit branch instruction. */
c3b7224a
NC
5242 if ((s3_inst.relax_inst != 0x8000)
5243 && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511))
1c0d3aa6 5244 {
c3b7224a
NC
5245 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */
5246 s3_inst.relax_size = 2;
1c0d3aa6
NC
5247 }
5248 else
5249 {
c3b7224a 5250 s3_inst.relax_inst = 0x8000;
1c0d3aa6 5251 }
1c0d3aa6
NC
5252}
5253
5254static void
c3b7224a 5255s3_do16_branch (char *str)
1c0d3aa6 5256{
c3b7224a 5257 if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
f9e53abc 5258 || s3_end_of_line (str) == (int) s3_FAIL))
1c0d3aa6
NC
5259 {
5260 ;
5261 }
c3b7224a 5262 else if (s3_inst.reloc.exp.X_add_symbol == 0)
1c0d3aa6 5263 {
c3b7224a 5264 s3_inst.error = _("lacking label");
1c0d3aa6 5265 }
c3b7224a 5266 else if (!(s3_inst.reloc.exp.X_add_number >= -512
f9e53abc 5267 && s3_inst.reloc.exp.X_add_number <= 511))
1c0d3aa6 5268 {
c3b7224a 5269 s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
1c0d3aa6
NC
5270 }
5271 else
5272 {
c3b7224a
NC
5273 s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5274 s3_inst.reloc.pc_rel = 1;
5275 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);
5276 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff);
5277 s3_inst.relax_size = 4;
1c0d3aa6
NC
5278 }
5279}
5280
c3b7224a
NC
5281/* Return true if the given symbol should be considered local for s3_PIC. */
5282static bfd_boolean
5283s3_pic_need_relax (symbolS *sym, asection *segtype)
1c0d3aa6 5284{
c3b7224a
NC
5285 asection *symsec;
5286 bfd_boolean linkonce;
1c0d3aa6 5287
c3b7224a
NC
5288 /* Handle the case of a symbol equated to another symbol. */
5289 while (symbol_equated_reloc_p (sym))
1c0d3aa6 5290 {
c3b7224a 5291 symbolS *n;
1c0d3aa6 5292
c3b7224a
NC
5293 /* It's possible to get a loop here in a badly written
5294 program. */
5295 n = symbol_get_value_expression (sym)->X_add_symbol;
5296 if (n == sym)
5297 break;
5298 sym = n;
1c0d3aa6 5299 }
1c0d3aa6 5300
c3b7224a 5301 symsec = S_GET_SEGMENT (sym);
1c0d3aa6 5302
c3b7224a
NC
5303 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5304 linkonce = FALSE;
5305 if (symsec != segtype && ! S_IS_LOCAL (sym))
1c0d3aa6 5306 {
fd361982 5307 if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0)
c3b7224a 5308 linkonce = TRUE;
1c0d3aa6 5309
c3b7224a 5310 /* The GNU toolchain uses an extension for ELF: a section
f9e53abc
NC
5311 beginning with the magic string .gnu.linkonce is a linkonce
5312 section. */
c3b7224a
NC
5313 if (strncmp (segment_name (symsec), ".gnu.linkonce",
5314 sizeof ".gnu.linkonce" - 1) == 0)
5315 linkonce = TRUE;
1c0d3aa6 5316 }
1c0d3aa6 5317
c3b7224a 5318 /* This must duplicate the test in adjust_reloc_syms. */
45dfa85a
AM
5319 return (!bfd_is_und_section (symsec)
5320 && !bfd_is_abs_section (symsec)
5321 && !bfd_is_com_section (symsec)
f9e53abc 5322 && !linkonce
c3b7224a
NC
5323#ifdef OBJ_ELF
5324 /* A global or weak symbol is treated as external. */
5325 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5326 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5327#endif
5328 );
5329}
1c0d3aa6 5330
c3b7224a
NC
5331static void
5332s3_parse_pce_inst (char *insnstr)
1c0d3aa6 5333{
c3b7224a
NC
5334 char c;
5335 char *p;
5336 char first[s3_MAX_LITERAL_POOL_SIZE];
5337 char second[s3_MAX_LITERAL_POOL_SIZE];
5338 struct s3_score_it pec_part_1;
1c0d3aa6 5339
c3b7224a
NC
5340 /* Get first part string of PCE. */
5341 p = strstr (insnstr, "||");
5342 c = *p;
5343 *p = '\0';
5344 sprintf (first, "%s", insnstr);
1c0d3aa6 5345
c3b7224a
NC
5346 /* Get second part string of PCE. */
5347 *p = c;
5348 p += 2;
5349 sprintf (second, "%s", p);
5350
5351 s3_parse_16_32_inst (first, FALSE);
5352 if (s3_inst.error)
5353 return;
5354
5355 memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst));
5356
5357 s3_parse_16_32_inst (second, FALSE);
5358 if (s3_inst.error)
5359 return;
5360
5361 if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE))
f9e53abc
NC
5362 || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE))
5363 || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE)))
1c0d3aa6 5364 {
33eaf5de 5365 s3_inst.error = _("pce instruction error (16 bit || 16 bit).");
cb580a26 5366 sprintf (s3_inst.str, "%s", insnstr);
c3b7224a 5367 return;
1c0d3aa6
NC
5368 }
5369
c3b7224a
NC
5370 if (!s3_inst.error)
5371 s3_gen_insn_frag (&pec_part_1, &s3_inst);
1c0d3aa6
NC
5372}
5373
c3b7224a
NC
5374/* s3: dsp. */
5375static void
5376s3_do16_dsp (char *str)
1c0d3aa6 5377{
c3b7224a 5378 int rd = 0;
1c0d3aa6 5379
f9e53abc 5380 /* Check 3d. */
c3b7224a 5381 if (s3_score3d == 0)
1c0d3aa6 5382 {
c3b7224a
NC
5383 s3_inst.error = _("score3d instruction.");
5384 return;
1c0d3aa6
NC
5385 }
5386
c3b7224a 5387 s3_skip_whitespace (str);
1c0d3aa6 5388
c3b7224a
NC
5389 if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL
5390 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 5391 {
c3b7224a 5392 return;
1c0d3aa6 5393 }
1c0d3aa6 5394 else
1c0d3aa6 5395 {
c3b7224a
NC
5396 s3_inst.relax_inst |= rd << 20;
5397 s3_inst.relax_size = 4;
1c0d3aa6 5398 }
1c0d3aa6
NC
5399}
5400
c3b7224a
NC
5401static void
5402s3_do16_dsp2 (char *str)
1c0d3aa6 5403{
f9e53abc 5404 /* Check 3d. */
c3b7224a 5405 if (s3_score3d == 0)
1c0d3aa6 5406 {
c3b7224a
NC
5407 s3_inst.error = _("score3d instruction.");
5408 return;
1c0d3aa6
NC
5409 }
5410
c3b7224a 5411 s3_skip_whitespace (str);
1c0d3aa6 5412
c3b7224a
NC
5413 if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
5414 || s3_skip_past_comma (&str) == (int) s3_FAIL
5415 || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
5416 || s3_end_of_line (str) == (int) s3_FAIL)
1c0d3aa6 5417 {
c3b7224a 5418 return;
1c0d3aa6
NC
5419 }
5420 else
5421 {
c3b7224a
NC
5422 s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20)
5423 | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10);
5424 s3_inst.relax_size = 4;
1c0d3aa6 5425 }
1c0d3aa6
NC
5426}
5427
c3b7224a
NC
5428static void
5429s3_do_dsp (char *str)
1c0d3aa6 5430{
f9e53abc 5431 /* Check 3d. */
c3b7224a 5432 if (s3_score3d == 0)
1c0d3aa6 5433 {
c3b7224a
NC
5434 s3_inst.error = _("score3d instruction.");
5435 return;
1c0d3aa6
NC
5436 }
5437
c3b7224a
NC
5438 s3_skip_whitespace (str);
5439
5440 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5441 || s3_skip_past_comma (&str) == (int) s3_FAIL
5442 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5443 || s3_end_of_line (str) == (int) s3_FAIL)
5444 return;
1c0d3aa6 5445
c3b7224a 5446 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
1c0d3aa6 5447 {
c3b7224a
NC
5448 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5449 s3_inst.relax_size = 2;
1c0d3aa6
NC
5450 }
5451 else
c3b7224a
NC
5452 s3_inst.relax_inst = 0x8000;
5453}
5454
5455static void
5456s3_do_dsp2 (char *str)
5457{
5458 int reg;
5459
f9e53abc 5460 /* Check 3d. */
c3b7224a 5461 if (s3_score3d == 0)
1c0d3aa6 5462 {
c3b7224a
NC
5463 s3_inst.error = _("score3d instruction.");
5464 return;
1c0d3aa6
NC
5465 }
5466
c3b7224a 5467 s3_skip_whitespace (str);
1c0d3aa6 5468
c3b7224a
NC
5469 if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5470 || s3_skip_past_comma (&str) == (int) s3_FAIL
5471 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5472 || s3_skip_past_comma (&str) == (int) s3_FAIL
5473 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5474 || s3_end_of_line (str) == (int) s3_FAIL)
5475 {
5476 return;
1c0d3aa6
NC
5477 }
5478 else
5479 {
c3b7224a
NC
5480 /* Check mulr, mulur rd is even number. */
5481 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
f9e53abc 5482 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
c3b7224a 5483 && (reg % 2))
1c0d3aa6 5484 {
c3b7224a
NC
5485 s3_inst.error = _("rd must be even number.");
5486 return;
1c0d3aa6
NC
5487 }
5488
c3b7224a
NC
5489 if ((((s3_inst.instruction >> 15) & 0x10) == 0)
5490 && (((s3_inst.instruction >> 10) & 0x10) == 0)
5491 && (((s3_inst.instruction >> 20) & 0x10) == 0)
5492 && (s3_inst.relax_inst != 0x8000)
5493 && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
1c0d3aa6 5494 {
c3b7224a
NC
5495 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
5496 | (((s3_inst.instruction >> 15) & 0xf) << 4);
5497 s3_inst.relax_size = 2;
1c0d3aa6
NC
5498 }
5499 else
c3b7224a
NC
5500 {
5501 s3_inst.relax_inst = 0x8000;
5502 }
1c0d3aa6 5503 }
1c0d3aa6
NC
5504}
5505
c3b7224a
NC
5506static void
5507s3_do_dsp3 (char *str)
1c0d3aa6 5508{
f9e53abc 5509 /* Check 3d. */
c3b7224a
NC
5510 if (s3_score3d == 0)
5511 {
5512 s3_inst.error = _("score3d instruction.");
5513 return;
5514 }
1c0d3aa6 5515
c3b7224a 5516 s3_skip_whitespace (str);
1c0d3aa6 5517
c3b7224a
NC
5518 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5519 || s3_skip_past_comma (&str) == (int) s3_FAIL
5520 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5521 || s3_end_of_line (str) == (int) s3_FAIL)
5522 return;
1c0d3aa6 5523
c3b7224a 5524 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
1c0d3aa6 5525 {
c3b7224a
NC
5526 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5527 s3_inst.relax_size = 2;
1c0d3aa6 5528 }
c3b7224a
NC
5529 else
5530 s3_inst.relax_inst = 0x8000;
1c0d3aa6
NC
5531}
5532
1c0d3aa6 5533
c3b7224a
NC
5534/* If we change section we must dump the literal pool first. */
5535static void
5536s3_s_score_bss (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 5537{
c3b7224a
NC
5538 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5539 demand_empty_rest_of_line ();
1c0d3aa6
NC
5540}
5541
c3b7224a
NC
5542static void
5543s3_s_score_text (int ignore)
1c0d3aa6 5544{
c3b7224a
NC
5545 obj_elf_text (ignore);
5546 record_alignment (now_seg, 2);
1c0d3aa6
NC
5547}
5548
c3b7224a
NC
5549static void
5550s3_score_s_section (int ignore)
1c0d3aa6 5551{
c3b7224a 5552 obj_elf_section (ignore);
fd361982 5553 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5554 record_alignment (now_seg, 2);
5555
1c0d3aa6
NC
5556}
5557
c3b7224a
NC
5558static void
5559s3_s_change_sec (int sec)
1c0d3aa6 5560{
c3b7224a 5561 segT seg;
1c0d3aa6 5562
c3b7224a
NC
5563#ifdef OBJ_ELF
5564 /* The ELF backend needs to know that we are changing sections, so
5565 that .previous works correctly. We could do something like check
5566 for an obj_section_change_hook macro, but that might be confusing
5567 as it would not be appropriate to use it in the section changing
5568 functions in read.c, since obj-elf.c intercepts those. FIXME:
5569 This should be cleaner, somehow. */
5570 obj_elf_section_change_hook ();
5571#endif
5572 switch (sec)
1c0d3aa6 5573 {
c3b7224a
NC
5574 case 'r':
5575 seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
a4dd6c97
AM
5576 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY
5577 | SEC_RELOC | SEC_DATA));
c3b7224a
NC
5578 if (strcmp (TARGET_OS, "elf") != 0)
5579 record_alignment (seg, 4);
5580 demand_empty_rest_of_line ();
5581 break;
5582 case 's':
5583 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
a4dd6c97
AM
5584 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
5585 | SEC_DATA | SEC_SMALL_DATA));
c3b7224a
NC
5586 if (strcmp (TARGET_OS, "elf") != 0)
5587 record_alignment (seg, 4);
5588 demand_empty_rest_of_line ();
5589 break;
1c0d3aa6 5590 }
1c0d3aa6
NC
5591}
5592
c3b7224a
NC
5593static void
5594s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
1c0d3aa6 5595{
c3b7224a 5596 long mask, off;
1c0d3aa6 5597
c3b7224a 5598 if (s3_cur_proc_ptr == (s3_procS *) NULL)
1c0d3aa6 5599 {
c3b7224a
NC
5600 as_warn (_(".mask outside of .ent"));
5601 demand_empty_rest_of_line ();
5602 return;
1c0d3aa6 5603 }
c3b7224a
NC
5604 if (get_absolute_expression_and_terminator (&mask) != ',')
5605 {
5606 as_warn (_("Bad .mask directive"));
5607 --input_line_pointer;
5608 demand_empty_rest_of_line ();
5609 return;
5610 }
5611 off = get_absolute_expression ();
5612 s3_cur_proc_ptr->reg_mask = mask;
5613 s3_cur_proc_ptr->reg_offset = off;
5614 demand_empty_rest_of_line ();
1c0d3aa6
NC
5615}
5616
c3b7224a
NC
5617static symbolS *
5618s3_get_symbol (void)
1c0d3aa6 5619{
c3b7224a
NC
5620 int c;
5621 char *name;
5622 symbolS *p;
1c0d3aa6 5623
d02603dc 5624 c = get_symbol_name (&name);
c3b7224a 5625 p = (symbolS *) symbol_find_or_make (name);
d02603dc 5626 (void) restore_line_pointer (c);
c3b7224a 5627 return p;
1c0d3aa6
NC
5628}
5629
c3b7224a
NC
5630static long
5631s3_get_number (void)
1c0d3aa6 5632{
c3b7224a
NC
5633 int negative = 0;
5634 long val = 0;
1c0d3aa6 5635
c3b7224a 5636 if (*input_line_pointer == '-')
1c0d3aa6 5637 {
c3b7224a
NC
5638 ++input_line_pointer;
5639 negative = 1;
1c0d3aa6 5640 }
c3b7224a
NC
5641 if (!ISDIGIT (*input_line_pointer))
5642 as_bad (_("expected simple number"));
5643 if (input_line_pointer[0] == '0')
1c0d3aa6 5644 {
c3b7224a 5645 if (input_line_pointer[1] == 'x')
1c0d3aa6 5646 {
c3b7224a
NC
5647 input_line_pointer += 2;
5648 while (ISXDIGIT (*input_line_pointer))
1c0d3aa6 5649 {
c3b7224a
NC
5650 val <<= 4;
5651 val |= hex_value (*input_line_pointer++);
1c0d3aa6 5652 }
c3b7224a 5653 return negative ? -val : val;
1c0d3aa6
NC
5654 }
5655 else
5656 {
c3b7224a
NC
5657 ++input_line_pointer;
5658 while (ISDIGIT (*input_line_pointer))
1c0d3aa6 5659 {
c3b7224a
NC
5660 val <<= 3;
5661 val |= *input_line_pointer++ - '0';
1c0d3aa6 5662 }
c3b7224a 5663 return negative ? -val : val;
1c0d3aa6 5664 }
c3b7224a
NC
5665 }
5666 if (!ISDIGIT (*input_line_pointer))
5667 {
5668 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5669 as_warn (_("invalid number"));
5670 return -1;
5671 }
5672 while (ISDIGIT (*input_line_pointer))
5673 {
5674 val *= 10;
5675 val += *input_line_pointer++ - '0';
5676 }
5677 return negative ? -val : val;
5678}
5679
5680/* The .aent and .ent directives. */
5681static void
5682s3_s_score_ent (int aent)
5683{
5684 symbolS *symbolP;
5685 int maybe_text;
5686
5687 symbolP = s3_get_symbol ();
5688 if (*input_line_pointer == ',')
5689 ++input_line_pointer;
5690 SKIP_WHITESPACE ();
5691 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5692 s3_get_number ();
5693
fd361982 5694 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5695 maybe_text = 1;
5696 else
5697 maybe_text = 0;
c3b7224a
NC
5698 if (!maybe_text)
5699 as_warn (_(".ent or .aent not in text section."));
5700 if (!aent && s3_cur_proc_ptr)
5701 as_warn (_("missing .end"));
5702 if (!aent)
5703 {
5704 s3_cur_proc_ptr = &s3_cur_proc;
5705 s3_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5706 s3_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5707 s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5708 s3_cur_proc_ptr->leaf = 0xdeafbeaf;
5709 s3_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5710 s3_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5711 s3_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5712 s3_cur_proc_ptr->isym = symbolP;
5713 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5714 ++s3_numprocs;
5715 if (debug_type == DEBUG_STABS)
5716 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5717 }
5718 demand_empty_rest_of_line ();
5719}
5720
5721static void
5722s3_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5723{
5724 char *backupstr;
5725 char str[30];
5726 long val;
5727 int i = 0;
5728
5729 backupstr = input_line_pointer;
5730
5731#ifdef OBJ_ELF
5732 if (s3_cur_proc_ptr == (s3_procS *) NULL)
5733 {
5734 as_warn (_(".frame outside of .ent"));
5735 demand_empty_rest_of_line ();
5736 return;
5737 }
5738 s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5739 SKIP_WHITESPACE ();
5740 s3_skip_past_comma (&backupstr);
5741 while (*backupstr != ',')
5742 {
5743 str[i] = *backupstr;
5744 i++;
5745 backupstr++;
5746 }
5747 str[i] = '\0';
5748 val = atoi (str);
5749
5750 SKIP_WHITESPACE ();
5751 s3_skip_past_comma (&backupstr);
5752 s3_cur_proc_ptr->frame_offset = val;
5753 s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5754
5755 SKIP_WHITESPACE ();
5756 s3_skip_past_comma (&backupstr);
5757 i = 0;
5758 while (*backupstr != '\n')
5759 {
5760 str[i] = *backupstr;
5761 i++;
5762 backupstr++;
5763 }
5764 str[i] = '\0';
5765 val = atoi (str);
5766 s3_cur_proc_ptr->leaf = val;
5767 SKIP_WHITESPACE ();
5768 s3_skip_past_comma (&backupstr);
5769
5770#endif /* OBJ_ELF */
5771 while (input_line_pointer != backupstr)
5772 input_line_pointer++;
5773}
5774
5775/* The .end directive. */
5776static void
5777s3_s_score_end (int x ATTRIBUTE_UNUSED)
5778{
5779 symbolS *p;
5780 int maybe_text;
5781
5782 /* Generate a .pdr section. */
5783 segT saved_seg = now_seg;
5784 subsegT saved_subseg = now_subseg;
c3b7224a
NC
5785 expressionS exp;
5786 char *fragp;
5787
5788 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5789 {
5790 p = s3_get_symbol ();
5791 demand_empty_rest_of_line ();
5792 }
5793 else
5794 p = NULL;
5795
fd361982 5796 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
c3b7224a
NC
5797 maybe_text = 1;
5798 else
5799 maybe_text = 0;
c3b7224a
NC
5800
5801 if (!maybe_text)
5802 as_warn (_(".end not in text section"));
5803 if (!s3_cur_proc_ptr)
5804 {
5805 as_warn (_(".end directive without a preceding .ent directive."));
5806 demand_empty_rest_of_line ();
5807 return;
5808 }
5809 if (p != NULL)
5810 {
9c2799c2 5811 gas_assert (S_GET_NAME (p));
c3b7224a
NC
5812 if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym)))
5813 as_warn (_(".end symbol does not match .ent symbol."));
5814 if (debug_type == DEBUG_STABS)
5815 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5816 }
5817 else
5818 as_warn (_(".end directive missing or unknown symbol"));
5819
5820 if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5821 (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5822 (s3_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5823 (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5824 (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5825
5826 else
5827 {
f9e53abc 5828 (void) frag_now_fix ();
9c2799c2 5829 gas_assert (s3_pdr_seg);
c3b7224a
NC
5830 subseg_set (s3_pdr_seg, 0);
5831 /* Write the symbol. */
5832 exp.X_op = O_symbol;
5833 exp.X_add_symbol = p;
5834 exp.X_add_number = 0;
5835 emit_expr (&exp, 4);
5836 fragp = frag_more (7 * 4);
5837 md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4);
5838 md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4);
5839 md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4);
5840 md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4);
5841 md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4);
5842 md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4);
5843 md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4);
5844 subseg_set (saved_seg, saved_subseg);
5845
5846 }
5847 s3_cur_proc_ptr = NULL;
5848}
5849
5850/* Handle the .set pseudo-op. */
5851static void
5852s3_s_score_set (int x ATTRIBUTE_UNUSED)
5853{
5854 int i = 0;
5855 char name[s3_MAX_LITERAL_POOL_SIZE];
5856 char * orig_ilp = input_line_pointer;
5857
5858 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5859 {
5860 name[i] = (char) * input_line_pointer;
5861 i++;
5862 ++input_line_pointer;
5863 }
5864
5865 name[i] = '\0';
5866
5867 if (strcmp (name, "nwarn") == 0)
5868 {
5869 s3_warn_fix_data_dependency = 0;
5870 }
5871 else if (strcmp (name, "fixdd") == 0)
5872 {
5873 s3_fix_data_dependency = 1;
5874 }
5875 else if (strcmp (name, "nofixdd") == 0)
5876 {
5877 s3_fix_data_dependency = 0;
5878 }
5879 else if (strcmp (name, "r1") == 0)
5880 {
5881 s3_nor1 = 0;
5882 }
5883 else if (strcmp (name, "nor1") == 0)
5884 {
5885 s3_nor1 = 1;
5886 }
5887 else if (strcmp (name, "optimize") == 0)
5888 {
5889 s3_g_opt = 1;
5890 }
5891 else if (strcmp (name, "volatile") == 0)
5892 {
5893 s3_g_opt = 0;
5894 }
5895 else if (strcmp (name, "pic") == 0)
5896 {
5897 s3_score_pic = s3_PIC;
5898 }
5899 else
5900 {
5901 input_line_pointer = orig_ilp;
5902 s_set (0);
5903 }
5904}
5905
5906/* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the
5907 $gp register for the function based on the function address, which is in the register
5908 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5909 specially by the linker. The result is:
5910 ldis gp, %hi(GP_DISP_LABEL)
5911 ori gp, %low(GP_DISP_LABEL)
5912 add gp, gp, .cpload argument
5913 The .cpload argument is normally r29. */
5914static void
5915s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5916{
5917 int reg;
5918 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5919
5920 /* If we are not generating s3_PIC code, .cpload is ignored. */
5921 if (s3_score_pic == s3_NO_PIC)
5922 {
5923 s_ignore (0);
5924 return;
5925 }
5926
5927 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5928 return;
5929
5930 demand_empty_rest_of_line ();
5931
5932 sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL);
5933 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5934 return;
5935
5936 sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL);
5937 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5938 return;
5939
5940 sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg);
5941 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5942 return;
5943}
5944
5945/* Handle the .cprestore pseudo-op. This stores $gp into a given
5946 offset from $sp. The offset is remembered, and after making a s3_PIC
5947 call $gp is restored from that location. */
5948static void
5949s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5950{
5951 int reg;
5952 int cprestore_offset;
5953 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5954
5955 /* If we are not generating s3_PIC code, .cprestore is ignored. */
5956 if (s3_score_pic == s3_NO_PIC)
5957 {
5958 s_ignore (0);
5959 return;
5960 }
5961
5962 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5963 || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL)
5964 {
5965 return;
5966 }
5967
5968 cprestore_offset = get_absolute_expression ();
5969
5970 if (cprestore_offset <= 0x3fff)
5971 {
5972 sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset);
5973 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5974 return;
5975 }
5976 else
5977 {
5978 int r1_bak;
5979
5980 r1_bak = s3_nor1;
5981 s3_nor1 = 0;
5982
5983 sprintf (insn_str, "li r1, %d", cprestore_offset);
5984 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5985 return;
5986
5987 sprintf (insn_str, "add r1, r1, r%d", reg);
5988 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5989 return;
5990
5991 sprintf (insn_str, "sw r%d, [r1]", s3_GP);
5992 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5993 return;
5994
5995 s3_nor1 = r1_bak;
5996 }
5997
5998 demand_empty_rest_of_line ();
5999}
6000
6001/* Handle the .gpword pseudo-op. This is used when generating s3_PIC
6002 code. It generates a 32 bit s3_GP relative reloc. */
6003static void
6004s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6005{
6006 expressionS ex;
6007 char *p;
6008
6009 /* When not generating s3_PIC code, this is treated as .word. */
6010 if (s3_score_pic == s3_NO_PIC)
6011 {
6012 cons (4);
6013 return;
6014 }
6015 expression (&ex);
6016 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6017 {
6018 as_bad (_("Unsupported use of .gpword"));
6019 ignore_rest_of_line ();
6020 }
6021 p = frag_more (4);
6022 s3_md_number_to_chars (p, (valueT) 0, 4);
6023 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6024 demand_empty_rest_of_line ();
6025}
6026
6027/* Handle the .cpadd pseudo-op. This is used when dealing with switch
6028 tables in s3_PIC code. */
6029static void
6030s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6031{
6032 int reg;
6033 char insn_str[s3_MAX_LITERAL_POOL_SIZE];
6034
6035 /* If we are not generating s3_PIC code, .cpload is ignored. */
6036 if (s3_score_pic == s3_NO_PIC)
6037 {
6038 s_ignore (0);
6039 return;
6040 }
6041
6042 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
6043 {
6044 return;
6045 }
6046 demand_empty_rest_of_line ();
6047
6048 /* Add $gp to the register named as an argument. */
6049 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP);
6050 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6051 return;
6052}
6053
6054#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
f9e53abc
NC
6055#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6056 do \
6057 { \
6058 if ((SIZE) >= 8) \
6059 (P2VAR) = 3; \
6060 else if ((SIZE) >= 4) \
6061 (P2VAR) = 2; \
6062 else if ((SIZE) >= 2) \
6063 (P2VAR) = 1; \
6064 else \
6065 (P2VAR) = 0; \
6066 } \
c3b7224a
NC
6067 while (0)
6068#endif
1c0d3aa6 6069
c3b7224a
NC
6070static void
6071s3_s_score_lcomm (int bytes_p)
6072{
6073 char *name;
6074 char c;
6075 char *p;
6076 int temp;
6077 symbolS *symbolP;
6078 segT current_seg = now_seg;
6079 subsegT current_subseg = now_subseg;
6080 const int max_alignment = 15;
6081 int align = 0;
6082 segT bss_seg = bss_section;
6083 int needs_align = 0;
6084
d02603dc 6085 c = get_symbol_name (&name);
c3b7224a 6086 p = input_line_pointer;
d02603dc 6087 (void) restore_line_pointer (c);
c3b7224a
NC
6088
6089 if (name == p)
6090 {
6091 as_bad (_("expected symbol name"));
6092 discard_rest_of_line ();
6093 return;
6094 }
6095
6096 SKIP_WHITESPACE ();
6097
6098 /* Accept an optional comma after the name. The comma used to be
6099 required, but Irix 5 cc does not generate it. */
6100 if (*input_line_pointer == ',')
6101 {
6102 ++input_line_pointer;
6103 SKIP_WHITESPACE ();
6104 }
6105
6106 if (is_end_of_line[(unsigned char)*input_line_pointer])
6107 {
6108 as_bad (_("missing size expression"));
6109 return;
6110 }
6111
6112 if ((temp = get_absolute_expression ()) < 0)
6113 {
6114 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6115 ignore_rest_of_line ();
6116 return;
6117 }
6118
6119#if defined (TC_SCORE)
6120 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6121 {
6122 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
fd361982
AM
6123 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6124 {
6125 bss_seg = subseg_new (".sbss", 1);
6126 seg_info (bss_seg)->bss = 1;
a4dd6c97 6127 if (!bfd_set_section_flags (bss_seg, SEC_ALLOC | SEC_SMALL_DATA))
fd361982
AM
6128 as_warn (_("error setting flags for \".sbss\": %s"),
6129 bfd_errmsg (bfd_get_error ()));
fd361982 6130 }
c3b7224a 6131 }
1c0d3aa6 6132#endif
1c0d3aa6 6133
c3b7224a
NC
6134 SKIP_WHITESPACE ();
6135 if (*input_line_pointer == ',')
6136 {
6137 ++input_line_pointer;
6138 SKIP_WHITESPACE ();
6139
6140 if (is_end_of_line[(unsigned char)*input_line_pointer])
1c0d3aa6 6141 {
c3b7224a
NC
6142 as_bad (_("missing alignment"));
6143 return;
1c0d3aa6 6144 }
1c0d3aa6
NC
6145 else
6146 {
c3b7224a
NC
6147 align = get_absolute_expression ();
6148 needs_align = 1;
1c0d3aa6 6149 }
1c0d3aa6 6150 }
1c0d3aa6 6151
c3b7224a
NC
6152 if (!needs_align)
6153 {
6154 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
1c0d3aa6 6155
c3b7224a
NC
6156 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6157 if (align)
6158 record_alignment (bss_seg, align);
6159 }
1c0d3aa6 6160
c3b7224a
NC
6161 if (needs_align)
6162 {
6163 if (bytes_p)
6164 {
6165 /* Convert to a power of 2. */
6166 if (align != 0)
6167 {
6168 unsigned int i;
1c0d3aa6 6169
c3b7224a
NC
6170 for (i = 0; align != 0; align >>= 1, ++i)
6171 ;
6172 align = i - 1;
6173 }
6174 }
6175
6176 if (align > max_alignment)
6177 {
6178 align = max_alignment;
6179 as_warn (_("alignment too large; %d assumed"), align);
6180 }
6181 else if (align < 0)
6182 {
6183 align = 0;
6184 as_warn (_("alignment negative; 0 assumed"));
6185 }
6186
6187 record_alignment (bss_seg, align);
6188 }
6189 else
1c0d3aa6 6190 {
c3b7224a
NC
6191 /* Assume some objects may require alignment on some systems. */
6192#if defined (TC_ALPHA) && ! defined (VMS)
6193 if (temp > 1)
6194 {
6195 align = ffs (temp) - 1;
6196 if (temp % (1 << align))
6197 abort ();
6198 }
6199#endif
6200 }
1c0d3aa6 6201
c3b7224a
NC
6202 *p = 0;
6203 symbolP = symbol_find_or_make (name);
6204 *p = c;
1c0d3aa6 6205
c3b7224a 6206 if (
a8eb42a8 6207#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
f9e53abc
NC
6208 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6209 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
c3b7224a 6210#endif
f9e53abc 6211 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
c3b7224a
NC
6212 {
6213 char *pfrag;
1c0d3aa6 6214
c3b7224a 6215 subseg_set (bss_seg, 1);
1c0d3aa6 6216
c3b7224a
NC
6217 if (align)
6218 frag_align (align, 0, 0);
1c0d3aa6 6219
c3b7224a
NC
6220 /* Detach from old frag. */
6221 if (S_GET_SEGMENT (symbolP) == bss_seg)
6222 symbol_get_frag (symbolP)->fr_symbol = NULL;
1c0d3aa6 6223
c3b7224a
NC
6224 symbol_set_frag (symbolP, frag_now);
6225 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6226 *pfrag = 0;
1c0d3aa6 6227
c3b7224a
NC
6228
6229 S_SET_SEGMENT (symbolP, bss_seg);
6230
6231#ifdef OBJ_COFF
6232 /* The symbol may already have been created with a preceding
6233 ".globl" directive -- be careful not to step on storage class
6234 in that case. Otherwise, set it to static. */
6235 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
1c0d3aa6 6236 {
c3b7224a 6237 S_SET_STORAGE_CLASS (symbolP, C_STAT);
1c0d3aa6 6238 }
c3b7224a
NC
6239#endif /* OBJ_COFF */
6240
6241#ifdef S_SET_SIZE
6242 S_SET_SIZE (symbolP, temp);
6243#endif
1c0d3aa6 6244 }
c3b7224a
NC
6245 else
6246 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
1c0d3aa6 6247
c3b7224a
NC
6248 subseg_set (current_seg, current_subseg);
6249
6250 demand_empty_rest_of_line ();
6251}
6252
6253static void
6254s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab)
6255{
6256 int i = 0;
6257 int len = strlen (r->name) + 2;
325801bd
TS
6258 char *buf = XNEWVEC (char, len);
6259 char *buf2 = XNEWVEC (char, len);
c3b7224a
NC
6260
6261 strcpy (buf + i, r->name);
6262 for (i = 0; buf[i]; i++)
1c0d3aa6 6263 {
c3b7224a 6264 buf2[i] = TOUPPER (buf[i]);
1c0d3aa6 6265 }
c3b7224a 6266 buf2[i] = '\0';
1c0d3aa6 6267
c3b7224a
NC
6268 hash_insert (htab, buf, (void *) r);
6269 hash_insert (htab, buf2, (void *) r);
1c0d3aa6
NC
6270}
6271
c3b7224a
NC
6272static void
6273s3_build_reg_hsh (struct s3_reg_map *map)
1c0d3aa6 6274{
c3b7224a
NC
6275 const struct s3_reg_entry *r;
6276
6277 if ((map->htab = hash_new ()) == NULL)
1c0d3aa6 6278 {
c3b7224a 6279 as_fatal (_("virtual memory exhausted"));
1c0d3aa6 6280 }
c3b7224a 6281 for (r = map->names; r->name != NULL; r++)
1c0d3aa6 6282 {
c3b7224a 6283 s3_insert_reg (r, map->htab);
1c0d3aa6
NC
6284 }
6285}
6286
c3b7224a 6287/* Iterate over the base tables to create the instruction patterns. */
1c0d3aa6 6288static void
c3b7224a 6289s3_build_score_ops_hsh (void)
1c0d3aa6 6290{
c3b7224a
NC
6291 unsigned int i;
6292 static struct obstack insn_obstack;
1c0d3aa6 6293
c3b7224a
NC
6294 obstack_begin (&insn_obstack, 4000);
6295 for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
6296 {
6297 const struct s3_asm_opcode *insn = s3_score_insns + i;
e57e6ddc 6298 size_t len = strlen (insn->template_name);
d3ce72d0
NC
6299 struct s3_asm_opcode *new_opcode;
6300 char *template_name;
6301 new_opcode = (struct s3_asm_opcode *)
f9e53abc 6302 obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
d3ce72d0 6303 template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
1c0d3aa6 6304
d3ce72d0
NC
6305 strcpy (template_name, insn->template_name);
6306 new_opcode->template_name = template_name;
6307 new_opcode->parms = insn->parms;
6308 new_opcode->value = insn->value;
6309 new_opcode->relax_value = insn->relax_value;
6310 new_opcode->type = insn->type;
6311 new_opcode->bitmask = insn->bitmask;
6312 hash_insert (s3_score_ops_hsh, new_opcode->template_name,
6313 (void *) new_opcode);
c3b7224a
NC
6314 }
6315}
1c0d3aa6 6316
c3b7224a
NC
6317static void
6318s3_build_dependency_insn_hsh (void)
6319{
6320 unsigned int i;
6321 static struct obstack dependency_obstack;
1c0d3aa6 6322
c3b7224a
NC
6323 obstack_begin (&dependency_obstack, 4000);
6324 for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
6325 {
6326 const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
e57e6ddc 6327 size_t len = strlen (tmp->insn_name);
d3ce72d0 6328 struct s3_insn_to_dependency *new_i2n;
b9bb4a93 6329 char *buf;
1c0d3aa6 6330
d3ce72d0 6331 new_i2n = (struct s3_insn_to_dependency *)
f9e53abc
NC
6332 obstack_alloc (&dependency_obstack,
6333 sizeof (struct s3_insn_to_dependency));
b9bb4a93 6334 buf = (char *) obstack_alloc (&dependency_obstack, len + 1);
1c0d3aa6 6335
b9bb4a93
TS
6336 strcpy (buf, tmp->insn_name);
6337 new_i2n->insn_name = buf;
d3ce72d0
NC
6338 new_i2n->type = tmp->type;
6339 hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name,
6340 (void *) new_i2n);
1c0d3aa6 6341 }
c3b7224a 6342}
1c0d3aa6 6343
c3b7224a
NC
6344static void
6345s_score_bss (int ignore ATTRIBUTE_UNUSED)
6346{
6347 if (score3)
6348 return s3_s_score_bss (ignore);
6349 else
6350 return s7_s_score_bss (ignore);
1c0d3aa6
NC
6351}
6352
c3b7224a
NC
6353static void
6354s_score_text (int ignore)
1c0d3aa6 6355{
c3b7224a
NC
6356 if (score3)
6357 return s3_s_score_text (ignore);
6358 else
6359 return s7_s_score_text (ignore);
6360}
6361
6362static void
6363s_section (int ignore)
6364{
6365 if (score3)
6366 return s3_score_s_section (ignore);
6367 else
6368 return s7_s_section (ignore);
6369}
1c0d3aa6 6370
c3b7224a
NC
6371static void
6372s_change_sec (int sec)
6373{
6374 if (score3)
6375 return s3_s_change_sec (sec);
1c0d3aa6 6376 else
c3b7224a
NC
6377 return s7_s_change_sec (sec);
6378}
1c0d3aa6 6379
c3b7224a
NC
6380static void
6381s_score_mask (int reg_type ATTRIBUTE_UNUSED)
6382{
6383 if (score3)
6384 return s3_s_score_mask (reg_type);
6385 else
6386 return s7_s_score_mask (reg_type);
1c0d3aa6
NC
6387}
6388
c3b7224a
NC
6389static void
6390s_score_ent (int aent)
1c0d3aa6 6391{
c3b7224a
NC
6392 if (score3)
6393 return s3_s_score_ent (aent);
6394 else
6395 return s7_s_score_ent (aent);
1c0d3aa6
NC
6396}
6397
c3b7224a
NC
6398static void
6399s_score_frame (int ignore ATTRIBUTE_UNUSED)
6400{
6401 if (score3)
6402 return s3_s_score_frame (ignore);
6403 else
6404 return s7_s_score_frame (ignore);
6405}
1c0d3aa6 6406
c3b7224a
NC
6407static void
6408s_score_end (int x ATTRIBUTE_UNUSED)
6409{
6410 if (score3)
6411 return s3_s_score_end (x);
6412 else
6413 return s7_s_score_end (x);
6414}
1c0d3aa6 6415
c3b7224a
NC
6416static void
6417s_score_set (int x ATTRIBUTE_UNUSED)
1c0d3aa6 6418{
c3b7224a
NC
6419 if (score3)
6420 return s3_s_score_set (x);
6421 else
6422 return s7_s_score_set (x);
6423}
1c0d3aa6 6424
c3b7224a
NC
6425static void
6426s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6427{
6428 if (score3)
6429 return s3_s_score_cpload (ignore);
6430 else
6431 return s7_s_score_cpload (ignore);
6432}
1c0d3aa6 6433
c3b7224a
NC
6434static void
6435s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 6436{
c3b7224a
NC
6437 if (score3)
6438 return s3_s_score_cprestore (ignore);
f9e53abc 6439 else
c3b7224a
NC
6440 return s7_s_score_cprestore (ignore);
6441}
6442
6443static void
6444s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6445{
6446 if (score3)
6447 return s3_s_score_gpword (ignore);
f9e53abc 6448 else
c3b7224a 6449 return s7_s_score_gpword (ignore);
1c0d3aa6
NC
6450}
6451
c3b7224a
NC
6452static void
6453s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
1c0d3aa6 6454{
c3b7224a
NC
6455 if (score3)
6456 return s3_s_score_cpadd (ignore);
f9e53abc 6457 else
c3b7224a
NC
6458 return s7_s_score_cpadd (ignore);
6459}
1c0d3aa6 6460
c3b7224a
NC
6461static void
6462s_score_lcomm (int bytes_p)
6463{
6464 if (score3)
6465 return s3_s_score_lcomm (bytes_p);
f9e53abc 6466 else
c3b7224a 6467 return s7_s_score_lcomm (bytes_p);
1c0d3aa6
NC
6468}
6469
c3b7224a
NC
6470static void
6471s3_assemble (char *str)
6472{
6473 know (str);
6474 know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
6475
6476 memset (&s3_inst, '\0', sizeof (s3_inst));
6477 if (s3_INSN_IS_PCE_P (str))
6478 s3_parse_pce_inst (str);
6479 else if (s3_INSN_IS_48_P (str))
6480 s3_parse_48_inst (str, TRUE);
6481 else
6482 s3_parse_16_32_inst (str, TRUE);
1c0d3aa6 6483
c3b7224a
NC
6484 if (s3_inst.error)
6485 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
6486}
1c0d3aa6 6487
1c0d3aa6 6488static void
91d6fa6a 6489s3_operand (expressionS * exp)
1c0d3aa6 6490{
c3b7224a
NC
6491 if (s3_in_my_get_expression)
6492 {
91d6fa6a 6493 exp->X_op = O_illegal;
c3b7224a
NC
6494 if (s3_inst.error == NULL)
6495 {
6496 s3_inst.error = _("bad expression");
6497 }
6498 }
1c0d3aa6
NC
6499}
6500
6501static void
c3b7224a 6502s3_begin (void)
1c0d3aa6 6503{
c3b7224a
NC
6504 unsigned int i;
6505 segT seg;
6506 subsegT subseg;
6507
6508 if ((s3_score_ops_hsh = hash_new ()) == NULL)
6509 as_fatal (_("virtual memory exhausted"));
6510
6511 s3_build_score_ops_hsh ();
6512
6513 if ((s3_dependency_insn_hsh = hash_new ()) == NULL)
6514 as_fatal (_("virtual memory exhausted"));
6515
6516 s3_build_dependency_insn_hsh ();
6517
6518 for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
6519 s3_build_reg_hsh (s3_all_reg_maps + i);
6520
6521 /* Initialize dependency vector. */
6522 s3_init_dependency_vector ();
6523
6524 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6525 seg = now_seg;
6526 subseg = now_subseg;
6527 s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
fd361982
AM
6528 bfd_set_section_flags (s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6529 bfd_set_section_alignment (s3_pdr_seg, 2);
c3b7224a
NC
6530 subseg_set (seg, subseg);
6531
6532 if (s3_USE_GLOBAL_POINTER_OPT)
6533 bfd_set_gp_size (stdoutput, s3_g_switch_value);
1c0d3aa6
NC
6534}
6535
6536static void
c3b7224a 6537s3_number_to_chars (char *buf, valueT val, int n)
1c0d3aa6 6538{
c3b7224a
NC
6539 if (target_big_endian)
6540 number_to_chars_bigendian (buf, val, n);
6541 else
6542 number_to_chars_littleendian (buf, val, n);
6543}
6544
6545static valueT
6546s3_normal_chars_to_number (char *buf, int n)
6547{
6548 valueT result = 0;
6549 unsigned char *where = (unsigned char *)buf;
6550
6551 if (target_big_endian)
6552 {
6553 while (n--)
f9e53abc 6554 {
c3b7224a 6555 result <<= 8;
f9e53abc
NC
6556 result |= (*where++ & 255);
6557 }
c3b7224a
NC
6558 }
6559 else
6560 {
6561 while (n--)
f9e53abc 6562 {
c3b7224a 6563 result <<= 8;
f9e53abc
NC
6564 result |= (where[n] & 255);
6565 }
c3b7224a 6566 }
1c0d3aa6 6567
f9e53abc 6568 return result;
1c0d3aa6
NC
6569}
6570
6571static void
c3b7224a 6572s3_number_to_chars_littleendian (void *p, valueT data, int n)
1c0d3aa6 6573{
c3b7224a 6574 char *buf = (char *) p;
1c0d3aa6 6575
c3b7224a 6576 switch (n)
1c0d3aa6 6577 {
c3b7224a
NC
6578 case 4:
6579 md_number_to_chars (buf, data >> 16, 2);
6580 md_number_to_chars (buf + 2, data, 2);
1c0d3aa6 6581 break;
c3b7224a
NC
6582 case 6:
6583 md_number_to_chars (buf, data >> 32, 2);
6584 md_number_to_chars (buf + 2, data >> 16, 2);
6585 md_number_to_chars (buf + 4, data, 2);
6586 break;
6587 default:
6588 /* Error routine. */
6589 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
1c0d3aa6
NC
6590 break;
6591 }
6592}
6593
c3b7224a
NC
6594static valueT
6595s3_chars_to_number_littleendian (const void *p, int n)
1c0d3aa6 6596{
c3b7224a
NC
6597 char *buf = (char *) p;
6598 valueT result = 0;
1c0d3aa6 6599
c3b7224a 6600 switch (n)
1c0d3aa6 6601 {
c3b7224a
NC
6602 case 4:
6603 result = s3_normal_chars_to_number (buf, 2) << 16;
6604 result |= s3_normal_chars_to_number (buf + 2, 2);
6605 break;
6606 case 6:
6607 result = s3_normal_chars_to_number (buf, 2) << 32;
6608 result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
6609 result |= s3_normal_chars_to_number (buf + 4, 2);
6610 break;
6611 default:
6612 /* Error routine. */
6613 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6614 break;
1c0d3aa6 6615 }
c3b7224a
NC
6616
6617 return result;
1c0d3aa6
NC
6618}
6619
c3b7224a
NC
6620static void
6621s3_md_number_to_chars (char *buf, valueT val, int n)
1c0d3aa6 6622{
f9e53abc 6623 if (!target_big_endian && n >= 4)
c3b7224a
NC
6624 s3_number_to_chars_littleendian (buf, val, n);
6625 else
6626 md_number_to_chars (buf, val, n);
6627}
1c0d3aa6 6628
c3b7224a
NC
6629static valueT
6630s3_md_chars_to_number (char *buf, int n)
6631{
6632 valueT result = 0;
6633
6634 if (!target_big_endian && n >= 4)
6635 result = s3_chars_to_number_littleendian (buf, n);
6636 else
6637 result = s3_normal_chars_to_number (buf, n);
6638
6639 return result;
1c0d3aa6
NC
6640}
6641
6d4af3c2 6642static const char *
c3b7224a 6643s3_atof (int type, char *litP, int *sizeP)
1c0d3aa6 6644{
c3b7224a 6645 int prec;
3076e594 6646 LITTLENUM_TYPE words[MAX_LITTLENUMS];
c3b7224a
NC
6647 char *t;
6648 int i;
1c0d3aa6 6649
c3b7224a 6650 switch (type)
1c0d3aa6 6651 {
c3b7224a
NC
6652 case 'f':
6653 case 'F':
6654 case 's':
6655 case 'S':
6656 prec = 2;
6657 break;
6658 case 'd':
6659 case 'D':
6660 case 'r':
6661 case 'R':
6662 prec = 4;
6663 break;
6664 case 'x':
6665 case 'X':
6666 case 'p':
6667 case 'P':
6668 prec = 6;
6669 break;
6670 default:
6671 *sizeP = 0;
6672 return _("bad call to MD_ATOF()");
1c0d3aa6 6673 }
c3b7224a
NC
6674
6675 t = atof_ieee (input_line_pointer, type, words);
6676 if (t)
6677 input_line_pointer = t;
6678 *sizeP = prec * 2;
6679
6680 if (target_big_endian)
1c0d3aa6 6681 {
c3b7224a 6682 for (i = 0; i < prec; i++)
1c0d3aa6 6683 {
c3b7224a
NC
6684 s3_md_number_to_chars (litP, (valueT) words[i], 2);
6685 litP += 2;
1c0d3aa6
NC
6686 }
6687 }
c3b7224a 6688 else
1c0d3aa6 6689 {
c3b7224a
NC
6690 for (i = 0; i < prec; i += 2)
6691 {
6692 s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
6693 s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
6694 litP += 4;
6695 }
1c0d3aa6 6696 }
c3b7224a
NC
6697
6698 return 0;
1c0d3aa6
NC
6699}
6700
c3b7224a
NC
6701static void
6702s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6703{
6704 know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
6705}
1c0d3aa6
NC
6706
6707static void
c3b7224a 6708s3_validate_fix (fixS *fixP)
1c0d3aa6 6709{
c3b7224a
NC
6710 fixP->fx_where += fixP->fx_frag->insn_addr;
6711}
1c0d3aa6 6712
c3b7224a
NC
6713static int
6714s3_force_relocation (struct fix *fixp)
6715{
6716 int retval = 0;
1c0d3aa6 6717
c3b7224a
NC
6718 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6719 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6720 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6721 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6722 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
f9e53abc 6723 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
c3b7224a 6724 || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
1c0d3aa6 6725 {
c3b7224a 6726 retval = 1;
1c0d3aa6 6727 }
c3b7224a 6728 return retval;
1c0d3aa6
NC
6729}
6730
c3b7224a
NC
6731static bfd_boolean
6732s3_fix_adjustable (fixS * fixP)
1c0d3aa6 6733{
c3b7224a 6734 if (fixP->fx_addsy == NULL)
1c0d3aa6 6735 {
c3b7224a 6736 return 1;
1c0d3aa6 6737 }
c3b7224a 6738 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
f9e53abc 6739 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
1c0d3aa6 6740 {
c3b7224a 6741 return 0;
1c0d3aa6 6742 }
c3b7224a
NC
6743 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6744 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6745 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6746 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
1c0d3aa6 6747 {
c3b7224a 6748 return 0;
1c0d3aa6 6749 }
1c0d3aa6 6750
c3b7224a 6751 return 1;
1c0d3aa6
NC
6752}
6753
1c0d3aa6 6754static void
c3b7224a 6755s3_elf_final_processing (void)
1c0d3aa6 6756{
c3b7224a 6757 unsigned long val = 0;
1c0d3aa6 6758
c3b7224a
NC
6759 if (score3)
6760 val = E_SCORE_MACH_SCORE3;
6761 else if (score7)
6762 val = E_SCORE_MACH_SCORE7;
1c0d3aa6 6763
c3b7224a
NC
6764 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6765 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6766 elf_elfheader (stdoutput)->e_flags |= val;
1c0d3aa6 6767
c3b7224a 6768 if (s3_fix_data_dependency == 1)
1c0d3aa6 6769 {
c3b7224a 6770 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
1c0d3aa6 6771 }
c3b7224a 6772 if (s3_score_pic == s3_PIC)
1c0d3aa6 6773 {
c3b7224a 6774 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
1c0d3aa6 6775 }
c3b7224a 6776}
1c0d3aa6 6777
c3b7224a
NC
6778static int
6779s3_judge_size_before_relax (fragS * fragp, asection *sec)
6780{
6781 int change = 0;
1c0d3aa6 6782
c3b7224a
NC
6783 if (s3_score_pic == s3_NO_PIC)
6784 change = s3_nopic_need_relax (fragp->fr_symbol, 0);
1c0d3aa6 6785 else
c3b7224a 6786 change = s3_pic_need_relax (fragp->fr_symbol, sec);
1c0d3aa6 6787
c3b7224a
NC
6788 if (change == 1)
6789 {
6790 /* Only at the first time determining whether s3_GP instruction relax should be done,
33eaf5de 6791 return the difference between instruction size and instruction relax size. */
c3b7224a
NC
6792 if (fragp->fr_opcode == NULL)
6793 {
6794 fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
6795 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6796 return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
6797 }
1c0d3aa6 6798 }
c3b7224a
NC
6799
6800 return 0;
1c0d3aa6
NC
6801}
6802
c3b7224a
NC
6803static int
6804s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
1c0d3aa6 6805{
c3b7224a
NC
6806 if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6807 || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6808 return s3_judge_size_before_relax (fragp, sec);
1c0d3aa6 6809
c3b7224a
NC
6810 return 0;
6811}
1c0d3aa6 6812
c3b7224a
NC
6813static int
6814s3_relax_branch_inst32 (fragS * fragp)
6815{
6816 fragp->fr_opcode = NULL;
6817 return 0;
6818}
1c0d3aa6 6819
c3b7224a
NC
6820static int
6821s3_relax_branch_inst16 (fragS * fragp)
6822{
6823 int relaxable_p = 0;
6824 int frag_addr = fragp->fr_address + fragp->insn_addr;
6825 addressT symbol_address = 0;
6826 symbolS *s;
6827 offsetT offset;
6828 long value;
6829 unsigned long inst_value;
6830
6831 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6832
6833 s = fragp->fr_symbol;
6834 if (s == NULL)
6835 frag_addr = 0;
6836 else
8d1015a8 6837 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
c3b7224a
NC
6838
6839 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
6840 offset = (inst_value & 0x1ff) << 1;
6841 if ((offset & 0x200) == 0x200)
6842 offset |= 0xfffffc00;
6843
6844 value = offset + symbol_address - frag_addr;
6845
f9e53abc 6846 if (relaxable_p
c3b7224a
NC
6847 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6848 && fragp->fr_fix == 2
c3b7224a
NC
6849 && (S_IS_DEFINED (s)
6850 && !S_IS_COMMON (s)
6851 && !S_IS_EXTERNAL (s)))
1c0d3aa6 6852 {
c3b7224a
NC
6853 /* Relax branch 32 to branch 16. */
6854 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6855 fragp->fr_fix = 4;
6856 return 2;
1c0d3aa6 6857 }
c3b7224a
NC
6858 else
6859 return 0;
6860}
6861
6862static int
6863s3_relax_cmpbranch_inst32 (fragS * fragp)
6864{
6865 int relaxable_p = 0;
6866 symbolS *s;
6867 /* For sign bit. */
6868 long offset;
6869 long frag_addr = fragp->fr_address + fragp->insn_addr;
6870 long symbol_address = 0;
6871 long value;
6872 unsigned long inst_value;
6873
6874 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6875
6876 s = fragp->fr_symbol;
6877 if (s == NULL)
6878 frag_addr = 0;
6879 else
8d1015a8 6880 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
c3b7224a
NC
6881
6882 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
6883 offset = (inst_value & 0x1)
f9e53abc
NC
6884 | (((inst_value >> 7) & 0x7) << 1)
6885 | (((inst_value >> 21) & 0x1f) << 4);
c3b7224a
NC
6886 offset <<= 1;
6887 if ((offset & 0x200) == 0x200)
6888 offset |= 0xfffffe00;
6889
6890 value = offset + symbol_address - frag_addr;
6891 /* change the order of judging rule is because
33eaf5de 6892 1.not defined symbol or common symbol or external symbol will change
f9e53abc
NC
6893 bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
6894 2.if the flow is as before : it will results to recursive loop
c3b7224a
NC
6895 */
6896 if (fragp->fr_fix == 6)
f9e53abc 6897 {
c3b7224a
NC
6898 /* Have already relaxed! Just return 0 to terminate the loop. */
6899 return 0;
1c0d3aa6 6900 }
33eaf5de 6901 /* need to translate when extern or not defined or common symbol */
f9e53abc
NC
6902 else if ((relaxable_p
6903 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
8d1015a8 6904 && fragp->fr_fix == 4)
f9e53abc
NC
6905 || !S_IS_DEFINED (s)
6906 ||S_IS_COMMON (s)
6907 ||S_IS_EXTERNAL (s))
1c0d3aa6 6908 {
c3b7224a
NC
6909 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6910 fragp->fr_fix = 6;
6911 return 2;
1c0d3aa6
NC
6912 }
6913 else
f9e53abc 6914 {
c3b7224a
NC
6915 /* Never relax. Modify fr_opcode to NULL to verify it's value in
6916 md_apply_fix. */
6917 fragp->fr_opcode = NULL;
6918 return 0;
1c0d3aa6
NC
6919 }
6920}
6921
1c0d3aa6 6922
c3b7224a
NC
6923static int
6924s3_relax_other_inst32 (fragS * fragp)
1c0d3aa6 6925{
c3b7224a 6926 int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
1c0d3aa6 6927
c3b7224a
NC
6928 if (relaxable_p
6929 && fragp->fr_fix == 4)
1c0d3aa6 6930 {
c3b7224a
NC
6931 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6932 fragp->fr_fix = 2;
6933 return -2;
1c0d3aa6 6934 }
c3b7224a
NC
6935 else
6936 return 0;
6937}
1c0d3aa6 6938
c3b7224a
NC
6939static int
6940s3_relax_gp_and_pic_inst32 (void)
6941{
f9e53abc 6942 /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
c3b7224a
NC
6943 instructions. We don't change relax size here. */
6944 return 0;
6945}
1c0d3aa6 6946
c3b7224a
NC
6947static int
6948s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
6949{
6950 int grows = 0;
6951 int adjust_align_p = 0;
1c0d3aa6 6952
c3b7224a
NC
6953 /* If the instruction address is odd, make it half word align first. */
6954 if ((fragp->fr_address) % 2 != 0)
6955 {
6956 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
f9e53abc 6957 {
c3b7224a
NC
6958 fragp->insn_addr = 1;
6959 grows += 1;
6960 adjust_align_p = 1;
f9e53abc 6961 }
c3b7224a 6962 }
1c0d3aa6 6963
c3b7224a
NC
6964 switch (s3_RELAX_TYPE (fragp->fr_subtype))
6965 {
6966 case PC_DISP19div2:
6967 grows += s3_relax_branch_inst32 (fragp);
6968 break;
1c0d3aa6 6969
c3b7224a
NC
6970 case PC_DISP8div2:
6971 grows += s3_relax_branch_inst16 (fragp);
6972 break;
1c0d3aa6 6973
c3b7224a
NC
6974 case Insn_BCMP :
6975 grows += s3_relax_cmpbranch_inst32 (fragp);
6976 break;
1c0d3aa6 6977
c3b7224a
NC
6978 case Insn_GP:
6979 case Insn_PIC:
6980 grows += s3_relax_gp_and_pic_inst32 ();
6981 break;
1c0d3aa6 6982
c3b7224a
NC
6983 default:
6984 grows += s3_relax_other_inst32 (fragp);
6985 break;
1c0d3aa6
NC
6986 }
6987
c3b7224a
NC
6988 /* newly added */
6989 if (adjust_align_p && fragp->insn_addr)
8fce5f8c 6990 {
c3b7224a 6991 fragp->fr_fix += fragp->insn_addr;
8fce5f8c
ML
6992 }
6993
c3b7224a
NC
6994 return grows;
6995}
6996
6997static void
6998s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
6999{
90bd3c90
AM
7000 unsigned int r_old;
7001 unsigned int r_new;
c3b7224a
NC
7002 char backup[20];
7003 fixS *fixp;
7004
d3ce72d0
NC
7005 r_old = s3_RELAX_OLD (fragp->fr_subtype);
7006 r_new = s3_RELAX_NEW (fragp->fr_subtype);
1c0d3aa6 7007
c3b7224a
NC
7008 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
7009 if (fragp->fr_opcode == NULL)
8fce5f8c 7010 {
d3ce72d0
NC
7011 memcpy (backup, fragp->fr_literal, r_old);
7012 fragp->fr_fix = r_old;
8fce5f8c
ML
7013 }
7014 else
7015 {
d3ce72d0
NC
7016 memcpy (backup, fragp->fr_literal + r_old, r_new);
7017 fragp->fr_fix = r_new;
c3b7224a 7018 }
8fce5f8c 7019
c3b7224a 7020 fixp = fragp->tc_frag_data.fixp;
d3ce72d0 7021 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
c3b7224a
NC
7022 {
7023 if (fragp->fr_opcode)
7024 fixp->fx_done = 1;
7025 fixp = fixp->fx_next;
7026 }
7027 while (fixp && fixp->fx_frag == fragp)
7028 {
7029 if (fragp->fr_opcode)
d3ce72d0 7030 fixp->fx_where -= r_old + fragp->insn_addr;
c3b7224a
NC
7031 else
7032 fixp->fx_done = 1;
7033 fixp = fixp->fx_next;
8fce5f8c
ML
7034 }
7035
c3b7224a
NC
7036 if (fragp->insn_addr)
7037 {
7038 s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
7039 }
7040 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
7041 fragp->fr_fix += fragp->insn_addr;
1c0d3aa6
NC
7042}
7043
c3b7224a
NC
7044static long
7045s3_pcrel_from (fixS * fixP)
1c0d3aa6 7046{
c3b7224a 7047 long retval = 0;
1c0d3aa6 7048
c3b7224a
NC
7049 if (fixP->fx_addsy
7050 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
7051 && (fixP->fx_subsy == NULL))
1c0d3aa6 7052 {
c3b7224a 7053 retval = 0;
1c0d3aa6 7054 }
c3b7224a 7055 else
1c0d3aa6 7056 {
c3b7224a 7057 retval = fixP->fx_where + fixP->fx_frag->fr_address;
1c0d3aa6 7058 }
c3b7224a
NC
7059
7060 return retval;
1c0d3aa6
NC
7061}
7062
c3b7224a
NC
7063static valueT
7064s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7065{
fd361982 7066 int align = bfd_section_alignment (segment);
8d3842cd 7067 return ((size + (1 << align) - 1) & -(1 << align));
c3b7224a 7068}
1c0d3aa6
NC
7069
7070static void
c3b7224a 7071s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
1c0d3aa6 7072{
c3b7224a
NC
7073 offsetT value = *valP;
7074 offsetT newval;
7075 offsetT content;
7076 unsigned short HI, LO;
1c0d3aa6 7077
c3b7224a
NC
7078 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
7079
9c2799c2 7080 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
c3b7224a 7081 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
1c0d3aa6 7082 {
c3b7224a
NC
7083 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
7084 fixP->fx_done = 1;
1c0d3aa6
NC
7085 }
7086
c3b7224a
NC
7087 /* If this symbol is in a different section then we need to leave it for
7088 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
7089 so we have to undo it's effects here. */
7090 if (fixP->fx_pcrel)
1c0d3aa6 7091 {
c3b7224a
NC
7092 if (fixP->fx_addsy != NULL
7093 && S_IS_DEFINED (fixP->fx_addsy)
7094 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7095 value += md_pcrel_from (fixP);
1c0d3aa6 7096 }
1c0d3aa6 7097
c3b7224a
NC
7098 /* Remember value for emit_reloc. */
7099 fixP->fx_addnumber = value;
1c0d3aa6 7100
c3b7224a
NC
7101 switch (fixP->fx_r_type)
7102 {
7103 case BFD_RELOC_HI16_S:
7104 if (fixP->fx_done) /* For la rd, imm32. */
7105 {
7106 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7107 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
7108 newval |= (HI & 0x3fff) << 1;
7109 newval |= ((HI >> 14) & 0x3) << 16;
7110 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7111 }
7112 break;
7113 case BFD_RELOC_LO16:
7114 if (fixP->fx_done) /* For la rd, imm32. */
7115 {
7116 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7117 LO = (value) & 0xffff;
7118 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
7119 newval |= ((LO >> 14) & 0x3) << 16;
7120 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7121 }
7122 break;
7123 case BFD_RELOC_SCORE_JMP:
7124 {
7125 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7126 value = fixP->fx_offset;
7127 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
7128 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7129 }
7130 break;
1c0d3aa6 7131
c3b7224a
NC
7132 case BFD_RELOC_SCORE_IMM30:
7133 {
7134 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7135 value = fixP->fx_offset;
7136 value >>= 2;
7137 content = (content & ~0x7f7fff7f80LL)
f9e53abc
NC
7138 | (((value & 0xff) >> 0) << 7)
7139 | (((value & 0x7fff00) >> 8) << 16)
7140 | (((value & 0x3f800000) >> 23) << 32);
c3b7224a
NC
7141 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7142 break;
7143 }
1c0d3aa6 7144
c3b7224a
NC
7145 case BFD_RELOC_SCORE_IMM32:
7146 {
7147 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7148 value = fixP->fx_offset;
7149 content = (content & ~0x7f7fff7fe0LL)
f9e53abc
NC
7150 | ((value & 0x3ff) << 5)
7151 | (((value >> 10) & 0x7fff) << 16)
7152 | (((value >> 25) & 0x7f) << 32);
c3b7224a
NC
7153 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7154 break;
7155 }
1c0d3aa6 7156
c3b7224a
NC
7157 case BFD_RELOC_SCORE_BRANCH:
7158 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7159 value = fixP->fx_offset;
7160 else
7161 fixP->fx_done = 1;
7162
7163 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7164
7165 /* Don't check c-bit. */
7166 if (fixP->fx_frag->fr_opcode != 0)
7167 {
7168 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7169 {
7170 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7171 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7172 return;
7173 }
7174 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7175 content &= 0xfe00;
7176 content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7177 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7178 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
7179 fixP->fx_size = 2;
7180 }
7181 else
7182 {
7183 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7184 {
7185 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7186 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7187 return;
7188 }
7189 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7190 content &= 0xfc00fc01;
7191 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7192 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7193 }
7194 break;
7195 case BFD_RELOC_SCORE16_JMP:
7196 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7197 content &= 0xf001;
7198 value = fixP->fx_offset & 0xfff;
7199 content = (content & 0xfc01) | (value & 0xffe);
7200 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7201 break;
f9e53abc 7202 case BFD_RELOC_SCORE16_BRANCH:
c3b7224a
NC
7203 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7204 /* Don't check c-bit. */
7205 if (fixP->fx_frag->fr_opcode != 0)
7206 {
7207 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7208 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7209 value = fixP->fx_offset;
7210 else
7211 fixP->fx_done = 1;
7212 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7213 {
7214 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7215 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7216 return;
7217 }
7218 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7219 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7220 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7221 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7222 fixP->fx_size = 4;
7223 break;
7224 }
7225 else
7226 {
2b0f3761 7227 /* In different section. */
c3b7224a
NC
7228 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7229 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7230 value = fixP->fx_offset;
7231 else
7232 fixP->fx_done = 1;
7233
7234 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7235 {
7236 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7237 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7238 return;
7239 }
7240
7241 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7242 content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7243 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7244 break;
7245 }
7246
f9e53abc 7247 break;
c3b7224a
NC
7248
7249 case BFD_RELOC_SCORE_BCMP:
7250 if (fixP->fx_frag->fr_opcode != 0)
7251 {
7252 char *buf_ptr = buf;
7253 buf_ptr += 2;
7254
7255 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7256 value = fixP->fx_offset;
7257 else
7258 fixP->fx_done = 1;
7259
f9e53abc 7260 /* NOTE!!!
c3b7224a
NC
7261 bcmp -> cmp! and branch, so value -= 2. */
7262 value -= 2;
7263
7264 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7265 {
7266 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7267 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value);
c3b7224a
NC
7268 return;
7269 }
7270
7271 content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
7272 content &= 0xfc00fc01;
7273 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7274 s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
7275 /* change relocation type to BFD_RELOC_SCORE_BRANCH */
7276 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7277 fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
7278 break;
7279 }
7280 else
7281 {
7282 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7283 value = fixP->fx_offset;
7284 else
7285 fixP->fx_done = 1;
1c0d3aa6 7286
c3b7224a 7287 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
1c0d3aa6 7288
c3b7224a
NC
7289 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7290 {
7291 as_bad_where (fixP->fx_file, fixP->fx_line,
33eaf5de 7292 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value);
c3b7224a
NC
7293 return;
7294 }
1c0d3aa6 7295
c3b7224a
NC
7296 value >>= 1;
7297 content &= ~0x03e00381;
7298 content = content
f9e53abc
NC
7299 | (value & 0x1)
7300 | (((value & 0xe) >> 1) << 7)
7301 | (((value & 0x1f0) >> 4) << 21);
1c0d3aa6 7302
c3b7224a
NC
7303 s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7304 break;
7305 }
1c0d3aa6 7306
c3b7224a
NC
7307 case BFD_RELOC_8:
7308 if (fixP->fx_done || fixP->fx_pcrel)
7309 s3_md_number_to_chars (buf, value, 1);
7310#ifdef OBJ_ELF
7311 else
1c0d3aa6 7312 {
c3b7224a
NC
7313 value = fixP->fx_offset;
7314 s3_md_number_to_chars (buf, value, 1);
1c0d3aa6 7315 }
1c0d3aa6 7316#endif
c3b7224a 7317 break;
1c0d3aa6 7318
c3b7224a
NC
7319 case BFD_RELOC_16:
7320 if (fixP->fx_done || fixP->fx_pcrel)
7321 s3_md_number_to_chars (buf, value, 2);
7322#ifdef OBJ_ELF
7323 else
1c0d3aa6 7324 {
c3b7224a
NC
7325 value = fixP->fx_offset;
7326 s3_md_number_to_chars (buf, value, 2);
1c0d3aa6 7327 }
c3b7224a
NC
7328#endif
7329 break;
7330 case BFD_RELOC_RVA:
7331 case BFD_RELOC_32:
7332 if (fixP->fx_done || fixP->fx_pcrel)
7333 md_number_to_chars (buf, value, 4);
7334#ifdef OBJ_ELF
1c0d3aa6
NC
7335 else
7336 {
c3b7224a
NC
7337 value = fixP->fx_offset;
7338 md_number_to_chars (buf, value, 4);
1c0d3aa6 7339 }
c3b7224a
NC
7340#endif
7341 break;
7342 case BFD_RELOC_VTABLE_INHERIT:
7343 fixP->fx_done = 0;
7344 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
7345 S_SET_WEAK (fixP->fx_addsy);
7346 break;
7347 case BFD_RELOC_VTABLE_ENTRY:
7348 fixP->fx_done = 0;
7349 break;
7350 case BFD_RELOC_SCORE_GPREL15:
7351 content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7352 /* c-bit. */
7353 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
7354 fixP->fx_r_type = BFD_RELOC_NONE;
7355 fixP->fx_done = 0;
7356 break;
7357 case BFD_RELOC_SCORE_GOT15:
7358 case BFD_RELOC_SCORE_DUMMY_HI16:
7359 case BFD_RELOC_SCORE_GOT_LO16:
7360 case BFD_RELOC_SCORE_CALL15:
7361 case BFD_RELOC_GPREL32:
7362 break;
7363 case BFD_RELOC_NONE:
7364 default:
7365 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
1c0d3aa6 7366 }
c3b7224a 7367}
1c0d3aa6 7368
c3b7224a
NC
7369static arelent **
7370s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7371{
7372 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
7373 arelent *reloc;
7374 bfd_reloc_code_real_type code;
585ba040 7375 const char *type;
1c0d3aa6 7376
325801bd 7377 reloc = retval[0] = XNEW (arelent);
c3b7224a 7378 retval[1] = NULL;
1c0d3aa6 7379
325801bd 7380 reloc->sym_ptr_ptr = XNEW (asymbol *);
c3b7224a
NC
7381 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7382 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7383 reloc->addend = fixp->fx_offset;
7384
7385 /* If this is a variant frag, we may need to adjust the existing
7386 reloc and generate a new one. */
7387 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
1c0d3aa6 7388 {
c3b7224a
NC
7389 /* Update instruction imm bit. */
7390 offsetT newval;
7391 unsigned short off;
7392 char *buf;
1c0d3aa6 7393
c3b7224a
NC
7394 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
7395 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7396 off = fixp->fx_offset >> 16;
7397 newval |= (off & 0x3fff) << 1;
7398 newval |= ((off >> 14) & 0x3) << 16;
7399 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
1c0d3aa6 7400
c3b7224a
NC
7401 buf += s3_INSN_SIZE;
7402 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7403 off = fixp->fx_offset & 0xffff;
7404 newval |= ((off & 0x3fff) << 1);
7405 newval |= (((off >> 14) & 0x3) << 16);
7406 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
1c0d3aa6 7407
325801bd 7408 retval[1] = XNEW (arelent);
c3b7224a 7409 retval[2] = NULL;
325801bd 7410 retval[1]->sym_ptr_ptr = XNEW (asymbol *);
c3b7224a
NC
7411 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7412 retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
7413
c3b7224a
NC
7414 retval[1]->addend = 0;
7415 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
9c2799c2 7416 gas_assert (retval[1]->howto != NULL);
c3b7224a
NC
7417
7418 fixp->fx_r_type = BFD_RELOC_HI16_S;
1c0d3aa6 7419 }
c3b7224a
NC
7420
7421 code = fixp->fx_r_type;
7422 switch (fixp->fx_r_type)
1c0d3aa6 7423 {
c3b7224a
NC
7424 case BFD_RELOC_32:
7425 if (fixp->fx_pcrel)
1c0d3aa6 7426 {
c3b7224a
NC
7427 code = BFD_RELOC_32_PCREL;
7428 break;
1c0d3aa6 7429 }
1a0670f3 7430 /* Fall through. */
c3b7224a
NC
7431 case BFD_RELOC_HI16_S:
7432 case BFD_RELOC_LO16:
7433 case BFD_RELOC_SCORE_JMP:
7434 case BFD_RELOC_SCORE_BRANCH:
7435 case BFD_RELOC_SCORE16_JMP:
7436 case BFD_RELOC_SCORE16_BRANCH:
7437 case BFD_RELOC_SCORE_BCMP:
7438 case BFD_RELOC_VTABLE_ENTRY:
7439 case BFD_RELOC_VTABLE_INHERIT:
7440 case BFD_RELOC_SCORE_GPREL15:
7441 case BFD_RELOC_SCORE_GOT15:
7442 case BFD_RELOC_SCORE_DUMMY_HI16:
7443 case BFD_RELOC_SCORE_GOT_LO16:
7444 case BFD_RELOC_SCORE_CALL15:
7445 case BFD_RELOC_GPREL32:
7446 case BFD_RELOC_NONE:
7447 case BFD_RELOC_SCORE_IMM30:
7448 case BFD_RELOC_SCORE_IMM32:
7449 code = fixp->fx_r_type;
7450 break;
7451 default:
7452 type = _("<unknown>");
7453 as_bad_where (fixp->fx_file, fixp->fx_line,
7454 _("cannot represent %s relocation in this object file format"), type);
7455 return NULL;
1c0d3aa6
NC
7456 }
7457
c3b7224a
NC
7458 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7459 if (reloc->howto == NULL)
1c0d3aa6 7460 {
c3b7224a
NC
7461 as_bad_where (fixp->fx_file, fixp->fx_line,
7462 _("cannot represent %s relocation in this object file format1"),
7463 bfd_get_reloc_code_name (code));
7464 return NULL;
7465 }
7466 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
7467 vtable entry to be used in the relocation's section offset. */
7468 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
7469 reloc->address = fixp->fx_offset;
7470
7471 return retval;
7472}
7473
7474void
7475md_assemble (char *str)
7476{
7477 if (score3)
7478 s3_assemble (str);
7479 else
7480 s7_assemble (str);
7481}
7482
7483/* We handle all bad expressions here, so that we can report the faulty
7484 instruction in the error message. */
7485void
91d6fa6a 7486md_operand (expressionS * exp)
c3b7224a
NC
7487{
7488 if (score3)
91d6fa6a 7489 s3_operand (exp);
c3b7224a 7490 else
91d6fa6a 7491 s7_operand (exp);
c3b7224a
NC
7492}
7493
7494/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7495 for use in the a.out file, and stores them in the array pointed to by buf.
7496 This knows about the endian-ness of the target machine and does
7497 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7498 2 (short) and 4 (long) Floating numbers are put out as a series of
7499 LITTLENUMS (shorts, here at least). */
7500void
7501md_number_to_chars (char *buf, valueT val, int n)
7502{
7503 if (score3)
7504 s3_number_to_chars (buf, val, n);
7505 else
7506 s7_number_to_chars (buf, val, n);
7507}
1c0d3aa6 7508
c3b7224a
NC
7509/* Turn a string in input_line_pointer into a floating point constant
7510 of type TYPE, and store the appropriate bytes in *LITP. The number
7511 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7512 returned, or NULL on OK.
7513
7514 Note that fp constants aren't represent in the normal way on the ARM.
7515 In big endian mode, things are as expected. However, in little endian
7516 mode fp constants are big-endian word-wise, and little-endian byte-wise
7517 within the words. For example, (double) 1.1 in big endian mode is
7518 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7519 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6d4af3c2 7520const char *
c3b7224a
NC
7521md_atof (int type, char *litP, int *sizeP)
7522{
7523 if (score3)
7524 return s3_atof (type, litP, sizeP);
7525 else
7526 return s7_atof (type, litP, sizeP);
7527}
1c0d3aa6 7528
c3b7224a
NC
7529void
7530score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
7531{
7532 if (score3)
7533 s3_frag_check (fragp);
7534 else
7535 s7_frag_check (fragp);
7536}
1c0d3aa6 7537
c3b7224a
NC
7538/* Implementation of TC_VALIDATE_FIX.
7539 Called before md_apply_fix() and after md_convert_frag(). */
7540void
7541score_validate_fix (fixS *fixP)
7542{
7543 if (score3)
7544 s3_validate_fix (fixP);
7545 else
7546 s7_validate_fix (fixP);
7547}
1c0d3aa6 7548
c3b7224a
NC
7549int
7550score_force_relocation (struct fix *fixp)
7551{
7552 if (score3)
7553 return s3_force_relocation (fixp);
7554 else
7555 return s7_force_relocation (fixp);
7556}
1c0d3aa6 7557
c3b7224a
NC
7558/* Implementation of md_frag_check.
7559 Called after md_convert_frag(). */
7560bfd_boolean
7561score_fix_adjustable (fixS * fixP)
7562{
7563 if (score3)
7564 return s3_fix_adjustable (fixP);
7565 else
7566 return s7_fix_adjustable (fixP);
7567}
1c0d3aa6 7568
c3b7224a
NC
7569void
7570score_elf_final_processing (void)
7571{
7572 if (score3)
7573 s3_elf_final_processing ();
7574 else
7575 s7_elf_final_processing ();
7576}
1c0d3aa6 7577
c3b7224a
NC
7578/* In this function, we determine whether s3_GP instruction should do relaxation,
7579 for the label being against was known now.
7580 Doing this here but not in md_relax_frag() can induce iteration times
7581 in stage of doing relax. */
7582int
7583md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
7584{
7585 if (score3)
7586 return s3_estimate_size_before_relax (fragp, sec);
7587 else
7588 return s7_estimate_size_before_relax (fragp, sec);
7589}
1c0d3aa6 7590
c3b7224a
NC
7591int
7592score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
7593{
7594 if (score3)
7595 return s3_relax_frag (sec, fragp, stretch);
f9e53abc 7596 else
c3b7224a
NC
7597 return s7_relax_frag (sec, fragp, stretch);
7598}
7599
7600void
7601md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7602{
7603 if (score3)
7604 return s3_convert_frag (abfd, sec, fragp);
1c0d3aa6 7605 else
c3b7224a
NC
7606 return s7_convert_frag (abfd, sec, fragp);
7607}
1c0d3aa6 7608
c3b7224a
NC
7609long
7610md_pcrel_from (fixS * fixP)
7611{
7612 if (score3)
7613 return s3_pcrel_from (fixP);
7614 else
7615 return s7_pcrel_from (fixP);
7616}
1c0d3aa6 7617
c3b7224a
NC
7618/* Round up a section size to the appropriate boundary. */
7619valueT
7620md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7621{
7622 if (score3)
7623 return s3_section_align (segment, size);
7624 else
7625 return s7_section_align (segment, size);
1c0d3aa6
NC
7626}
7627
c3b7224a
NC
7628void
7629md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1c0d3aa6 7630{
c3b7224a
NC
7631 if (score3)
7632 return s3_apply_fix (fixP, valP, seg);
7633 else
7634 return s7_apply_fix (fixP, valP, seg);
7635}
1c0d3aa6 7636
c3b7224a
NC
7637/* Translate internal representation of relocation info to BFD target format. */
7638arelent **
7639tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7640{
7641 if (score3)
7642 return s3_gen_reloc (section, fixp);
7643 else
7644 return s7_gen_reloc (section, fixp);
7645}
1c0d3aa6 7646
c3b7224a
NC
7647void
7648md_begin (void)
7649{
7650 s3_begin ();
7651 s7_begin ();
1c0d3aa6
NC
7652}
7653
7654static void
c3b7224a 7655score_set_mach (const char *arg)
1c0d3aa6 7656{
c3b7224a 7657 if (strcmp (arg, MARCH_SCORE3) == 0)
1c0d3aa6 7658 {
c3b7224a
NC
7659 score3 = 1;
7660 score7 = 0;
7661 s3_score3d = 1;
1c0d3aa6 7662 }
c3b7224a
NC
7663 else if (strcmp (arg, MARCH_SCORE7) == 0)
7664 {
7665 score3 = 0;
7666 score7 = 1;
7667 s7_score7d = 1;
7668 s7_university_version = 0;
7669 s7_vector_size = s7_SCORE7_PIPELINE;
7670 }
7671 else if (strcmp (arg, MARCH_SCORE5) == 0)
7672 {
7673 score3 = 0;
7674 score7 = 1;
7675 s7_score7d = 1;
7676 s7_university_version = 0;
7677 s7_vector_size = s7_SCORE5_PIPELINE;
7678 }
7679 else if (strcmp (arg, MARCH_SCORE5U) == 0)
7680 {
7681 score3 = 0;
7682 score7 = 1;
7683 s7_score7d = 1;
7684 s7_university_version = 1;
7685 s7_vector_size = s7_SCORE5_PIPELINE;
7686 }
7687 else
1c0d3aa6 7688 {
c3b7224a 7689 as_bad (_("unknown architecture `%s'\n"), arg);
1c0d3aa6
NC
7690 }
7691}
7692
c3b7224a 7693int
17b9d67d 7694md_parse_option (int c, const char *arg)
1c0d3aa6 7695{
c3b7224a
NC
7696 switch (c)
7697 {
7698#ifdef OPTION_EB
7699 case OPTION_EB:
7700 target_big_endian = 1;
7701 break;
7702#endif
7703#ifdef OPTION_EL
7704 case OPTION_EL:
7705 target_big_endian = 0;
7706 break;
7707#endif
7708 case OPTION_FIXDD:
7709 s3_fix_data_dependency = 1;
7710 s7_fix_data_dependency = 1;
7711 break;
7712 case OPTION_NWARN:
7713 s3_warn_fix_data_dependency = 0;
7714 s7_warn_fix_data_dependency = 0;
7715 break;
7716 case OPTION_SCORE5:
7717 score3 = 0;
7718 score7 = 1;
7719 s7_university_version = 0;
7720 s7_vector_size = s7_SCORE5_PIPELINE;
7721 break;
7722 case OPTION_SCORE5U:
7723 score3 = 0;
7724 score7 = 1;
7725 s7_university_version = 1;
7726 s7_vector_size = s7_SCORE5_PIPELINE;
7727 break;
7728 case OPTION_SCORE7:
7729 score3 = 0;
7730 score7 = 1;
7731 s7_score7d = 1;
7732 s7_university_version = 0;
7733 s7_vector_size = s7_SCORE7_PIPELINE;
7734 break;
7735 case OPTION_SCORE3:
7736 score3 = 1;
7737 score7 = 0;
7738 s3_score3d = 1;
7739 break;
7740 case OPTION_R1:
7741 s3_nor1 = 0;
7742 s7_nor1 = 0;
7743 break;
7744 case 'G':
7745 s3_g_switch_value = atoi (arg);
7746 s7_g_switch_value = atoi (arg);
7747 break;
7748 case OPTION_O0:
7749 s3_g_opt = 0;
7750 s7_g_opt = 0;
7751 break;
7752 case OPTION_SCORE_VERSION:
7753 printf (_("Sunplus-v2-0-0-20060510\n"));
7754 break;
7755 case OPTION_PIC:
7756 s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */
7757 s7_score_pic = s7_PIC;
7758 s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */
7759 s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */
7760 break;
7761 case OPTION_MARCH:
7762 score_set_mach (arg);
7763 break;
7764 default:
7765 return 0;
7766 }
7767 return 1;
1c0d3aa6
NC
7768}
7769
c3b7224a
NC
7770void
7771md_show_usage (FILE * fp)
1c0d3aa6 7772{
c3b7224a
NC
7773 fprintf (fp, _(" Score-specific assembler options:\n"));
7774#ifdef OPTION_EB
7775 fprintf (fp, _("\
7776 -EB\t\tassemble code for a big-endian cpu\n"));
7777#endif
7778
7779#ifdef OPTION_EL
7780 fprintf (fp, _("\
7781 -EL\t\tassemble code for a little-endian cpu\n"));
7782#endif
1c0d3aa6 7783
c3b7224a 7784 fprintf (fp, _("\
33eaf5de 7785 -FIXDD\t\tfix data dependencies\n"));
c3b7224a 7786 fprintf (fp, _("\
33eaf5de 7787 -NWARN\t\tdo not print warning message when fixing data dependencies\n"));
c3b7224a 7788 fprintf (fp, _("\
33eaf5de 7789 -SCORE5\t\tassemble code for target SCORE5\n"));
c3b7224a 7790 fprintf (fp, _("\
33eaf5de 7791 -SCORE5U\tassemble code for target SCORE5U\n"));
c3b7224a 7792 fprintf (fp, _("\
33eaf5de 7793 -SCORE7\t\tassemble code for target SCORE7 [default]\n"));
c3b7224a 7794 fprintf (fp, _("\
33eaf5de 7795 -SCORE3\t\tassemble code for target SCORE3\n"));
c3b7224a 7796 fprintf (fp, _("\
33eaf5de 7797 -march=score7\tassemble code for target SCORE7 [default]\n"));
c3b7224a 7798 fprintf (fp, _("\
33eaf5de 7799 -march=score3\tassemble code for target SCORE3\n"));
c3b7224a
NC
7800 fprintf (fp, _("\
7801 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
7802 fprintf (fp, _("\
33eaf5de 7803 -KPIC\t\tgenerate PIC\n"));
c3b7224a 7804 fprintf (fp, _("\
33eaf5de 7805 -O0\t\tdo not perform any optimizations\n"));
c3b7224a 7806 fprintf (fp, _("\
33eaf5de 7807 -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n"));
c3b7224a 7808 fprintf (fp, _("\
33eaf5de 7809 -V \t\tSunplus release version\n"));
c3b7224a 7810}
This page took 1.108353 seconds and 4 git commands to generate.