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