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