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