1 /* tc-score7.c -- Assembler for Score7
2 Copyright (C) 2009-2017 Free Software Foundation, Inc.
4 Brain.lin (brain.lin@sunplusct.com)
5 Mei Ligang (ligang@sunnorth.com.cn)
6 Pei-Lin Tsai (pltsai@sunplus.com)
8 This file is part of GAS, the GNU Assembler.
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)
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.
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,
23 MA 02110-1301, USA. */
28 #include "safe-ctype.h"
29 #include "opcode/score-inst.h"
30 #include "struc-symbol.h"
31 #include "libiberty.h"
34 #include "elf/score.h"
35 #include "dwarf2dbg.h"
38 static void s7_do_ldst_insn (char *);
39 static void s7_do_crdcrscrsimm5 (char *);
40 static void s7_do_ldst_unalign (char *);
41 static void s7_do_ldst_atomic (char *);
42 static void s7_do_ldst_cop (char *);
43 static void s7_do_macro_li_rdi32 (char *);
44 static void s7_do_macro_la_rdi32 (char *);
45 static void s7_do_macro_rdi32hi (char *);
46 static void s7_do_macro_rdi32lo (char *);
47 static void s7_do_macro_mul_rdrsrs (char *);
48 static void s7_do_macro_ldst_label (char *);
49 static void s7_do_branch (char *);
50 static void s7_do_jump (char *);
51 static void s7_do_empty (char *);
52 static void s7_do_rdrsrs (char *);
53 static void s7_do_rdsi16 (char *);
54 static void s7_do_rdrssi14 (char *);
55 static void s7_do_sub_rdsi16 (char *);
56 static void s7_do_sub_rdrssi14 (char *);
57 static void s7_do_rdrsi5 (char *);
58 static void s7_do_rdrsi14 (char *);
59 static void s7_do_rdi16 (char *);
60 static void s7_do_xrsi5 (char *);
61 static void s7_do_rdrs (char *);
62 static void s7_do_rdxrs (char *);
63 static void s7_do_rsrs (char *);
64 static void s7_do_rdcrs (char *);
65 static void s7_do_rdsrs (char *);
66 static void s7_do_rd (char *);
67 static void s7_do_rs (char *);
68 static void s7_do_i15 (char *);
69 static void s7_do_xi5x (char *);
70 static void s7_do_ceinst (char *);
71 static void s7_do_cache (char *);
72 static void s7_do16_rdrs (char *);
73 static void s7_do16_rs (char *);
74 static void s7_do16_xrs (char *);
75 static void s7_do16_mv_rdrs (char *);
76 static void s7_do16_hrdrs (char *);
77 static void s7_do16_rdhrs (char *);
78 static void s7_do16_rdi4 (char *);
79 static void s7_do16_rdi5 (char *);
80 static void s7_do16_xi5 (char *);
81 static void s7_do16_ldst_insn (char *);
82 static void s7_do16_ldst_imm_insn (char *);
83 static void s7_do16_push_pop (char *);
84 static void s7_do16_branch (char *);
85 static void s7_do16_jump (char *);
86 static void s7_do_rdi16_pic (char *);
87 static void s7_do_addi_s_pic (char *);
88 static void s7_do_addi_u_pic (char *);
89 static void s7_do_lw_pic (char *);
92 #define s7_PIC_CALL_REG 29
93 #define s7_MAX_LITERAL_POOL_SIZE 1024
94 #define s7_FAIL 0x80000000
96 #define s7_INSN_SIZE 4
97 #define s7_INSN16_SIZE 2
98 #define s7_RELAX_INST_NUM 3
100 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
101 #define s7_BAD_ARGS _("bad arguments to instruction")
102 #define s7_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
103 #define s7_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
104 #define s7_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
105 #define s7_BAD_SKIP_COMMA s7_BAD_ARGS
106 #define s7_BAD_GARBAGE _("garbage following instruction");
108 #define s7_skip_whitespace(str) while (*(str) == ' ') ++(str)
110 /* The name of the readonly data section. */
111 #define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
113 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
115 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
117 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
121 #define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
130 #define s7_RELAX_OLD(i) (((i) >> 23) & 0x7f)
131 #define s7_RELAX_NEW(i) (((i) >> 16) & 0x7f)
132 #define s7_RELAX_TYPE(i) (((i) >> 9) & 0x7f)
133 #define s7_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
134 #define s7_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
135 #define s7_RELAX_OPT(i) ((i) & 1)
136 #define s7_RELAX_OPT_CLEAR(i) ((i) & ~1)
138 #define s7_SET_INSN_ERROR(s) (s7_inst.error = (s))
139 #define s7_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
141 #define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type))
143 #define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \
144 ? s7_INSN16_SIZE : s7_INSN_SIZE)
146 #define s7_MAX_LITTLENUMS 6
147 #define s7_INSN_NAME_LEN 16
149 /* Relax will need some padding for alignment. */
150 #define s7_RELAX_PAD_BYTE 3
152 #define s7_USE_GLOBAL_POINTER_OPT 1
156 /* Enumeration matching entries in table above. */
157 enum s7_score_reg_type
159 s7_REG_TYPE_SCORE = 0,
160 #define REG_TYPE_FIRST s7_REG_TYPE_SCORE
161 s7_REG_TYPE_SCORE_SR = 1,
162 s7_REG_TYPE_SCORE_CR = 2,
166 enum s7_score_pic_level
171 static enum s7_score_pic_level s7_score_pic = s7_NO_PIC;
173 enum s7_insn_type_for_dependency
192 struct s7_insn_to_dependency
194 const char *insn_name;
195 enum s7_insn_type_for_dependency type;
198 struct s7_data_dependency
200 enum s7_insn_type_for_dependency pre_insn_type;
202 enum s7_insn_type_for_dependency cur_insn_type;
206 int warn_or_error; /* warning - 0; error - 1 */
209 static const struct s7_insn_to_dependency s7_insn_to_dependency_table[] =
211 /* pce instruction. */
213 /* conditional branch instruction. */
214 {"bcs", s7_D_cond_br},
215 {"bcc", s7_D_cond_br},
216 {"bgtu", s7_D_cond_br},
217 {"bleu", s7_D_cond_br},
218 {"beq", s7_D_cond_br},
219 {"bne", s7_D_cond_br},
220 {"bgt", s7_D_cond_br},
221 {"ble", s7_D_cond_br},
222 {"bge", s7_D_cond_br},
223 {"blt", s7_D_cond_br},
224 {"bmi", s7_D_cond_br},
225 {"bpl", s7_D_cond_br},
226 {"bvs", s7_D_cond_br},
227 {"bvc", s7_D_cond_br},
228 {"bcsl", s7_D_cond_br},
229 {"bccl", s7_D_cond_br},
230 {"bgtul", s7_D_cond_br},
231 {"bleul", s7_D_cond_br},
232 {"beql", s7_D_cond_br},
233 {"bnel", s7_D_cond_br},
234 {"bgtl", s7_D_cond_br},
235 {"blel", s7_D_cond_br},
236 {"bgel", s7_D_cond_br},
237 {"bltl", s7_D_cond_br},
238 {"bmil", s7_D_cond_br},
239 {"bpll", s7_D_cond_br},
240 {"bvsl", s7_D_cond_br},
241 {"bvcl", s7_D_cond_br},
242 {"bcs!", s7_D_cond_br},
243 {"bcc!", s7_D_cond_br},
244 {"bgtu!", s7_D_cond_br},
245 {"bleu!", s7_D_cond_br},
246 {"beq!", s7_D_cond_br},
247 {"bne!", s7_D_cond_br},
248 {"bgt!", s7_D_cond_br},
249 {"ble!", s7_D_cond_br},
250 {"bge!", s7_D_cond_br},
251 {"blt!", s7_D_cond_br},
252 {"bmi!", s7_D_cond_br},
253 {"bpl!", s7_D_cond_br},
254 {"bvs!", s7_D_cond_br},
255 {"bvc!", s7_D_cond_br},
256 {"brcs", s7_D_cond_br},
257 {"brcc", s7_D_cond_br},
258 {"brgtu", s7_D_cond_br},
259 {"brleu", s7_D_cond_br},
260 {"breq", s7_D_cond_br},
261 {"brne", s7_D_cond_br},
262 {"brgt", s7_D_cond_br},
263 {"brle", s7_D_cond_br},
264 {"brge", s7_D_cond_br},
265 {"brlt", s7_D_cond_br},
266 {"brmi", s7_D_cond_br},
267 {"brpl", s7_D_cond_br},
268 {"brvs", s7_D_cond_br},
269 {"brvc", s7_D_cond_br},
270 {"brcsl", s7_D_cond_br},
271 {"brccl", s7_D_cond_br},
272 {"brgtul", s7_D_cond_br},
273 {"brleul", s7_D_cond_br},
274 {"breql", s7_D_cond_br},
275 {"brnel", s7_D_cond_br},
276 {"brgtl", s7_D_cond_br},
277 {"brlel", s7_D_cond_br},
278 {"brgel", s7_D_cond_br},
279 {"brltl", s7_D_cond_br},
280 {"brmil", s7_D_cond_br},
281 {"brpll", s7_D_cond_br},
282 {"brvsl", s7_D_cond_br},
283 {"brvcl", s7_D_cond_br},
284 {"brcs!", s7_D_cond_br},
285 {"brcc!", s7_D_cond_br},
286 {"brgtu!", s7_D_cond_br},
287 {"brleu!", s7_D_cond_br},
288 {"breq!", s7_D_cond_br},
289 {"brne!", s7_D_cond_br},
290 {"brgt!", s7_D_cond_br},
291 {"brle!", s7_D_cond_br},
292 {"brge!", s7_D_cond_br},
293 {"brlt!", s7_D_cond_br},
294 {"brmi!", s7_D_cond_br},
295 {"brpl!", s7_D_cond_br},
296 {"brvs!", s7_D_cond_br},
297 {"brvc!", s7_D_cond_br},
298 {"brcsl!", s7_D_cond_br},
299 {"brccl!", s7_D_cond_br},
300 {"brgtul!", s7_D_cond_br},
301 {"brleul!", s7_D_cond_br},
302 {"breql!", s7_D_cond_br},
303 {"brnel!", s7_D_cond_br},
304 {"brgtl!", s7_D_cond_br},
305 {"brlel!", s7_D_cond_br},
306 {"brgel!", s7_D_cond_br},
307 {"brltl!", s7_D_cond_br},
308 {"brmil!", s7_D_cond_br},
309 {"brpll!", s7_D_cond_br},
310 {"brvsl!", s7_D_cond_br},
311 {"brvcl!", s7_D_cond_br},
312 /* conditional move instruction. */
313 {"mvcs", s7_D_cond_mv},
314 {"mvcc", s7_D_cond_mv},
315 {"mvgtu", s7_D_cond_mv},
316 {"mvleu", s7_D_cond_mv},
317 {"mveq", s7_D_cond_mv},
318 {"mvne", s7_D_cond_mv},
319 {"mvgt", s7_D_cond_mv},
320 {"mvle", s7_D_cond_mv},
321 {"mvge", s7_D_cond_mv},
322 {"mvlt", s7_D_cond_mv},
323 {"mvmi", s7_D_cond_mv},
324 {"mvpl", s7_D_cond_mv},
325 {"mvvs", s7_D_cond_mv},
326 {"mvvc", s7_D_cond_mv},
327 /* move spectial instruction. */
329 {"mftlb", s7_D_mftlb},
330 {"mtptlb", s7_D_mtptlb},
331 {"mtrtlb", s7_D_mtrtlb},
335 /* cache instruction. */
336 {"cache 8", s7_D_cached},
337 {"cache 9", s7_D_cached},
338 {"cache 10", s7_D_cached},
339 {"cache 11", s7_D_cached},
340 {"cache 12", s7_D_cached},
341 {"cache 13", s7_D_cached},
342 {"cache 14", s7_D_cached},
343 {"cache 24", s7_D_cached},
344 {"cache 26", s7_D_cached},
345 {"cache 27", s7_D_cached},
346 {"cache 29", s7_D_cached},
347 {"cache 30", s7_D_cached},
348 {"cache 31", s7_D_cached},
349 {"cache 0", s7_D_cachei},
350 {"cache 1", s7_D_cachei},
351 {"cache 2", s7_D_cachei},
352 {"cache 3", s7_D_cachei},
353 {"cache 4", s7_D_cachei},
354 {"cache 16", s7_D_cachei},
355 {"cache 17", s7_D_cachei},
356 /* load/store instruction. */
360 {"lbup!", s7_D_ldst},
379 {"push!", s7_D_ldst},
380 {"pushhi!", s7_D_ldst},
382 {"pophi!", s7_D_ldst},
392 /* load combine instruction. */
393 {"lcb", s7_D_ldcombine},
394 {"lcw", s7_D_ldcombine},
395 {"lce", s7_D_ldcombine},
398 static const struct s7_data_dependency s7_data_dependency_table[] =
400 /* Condition register. */
401 {s7_D_mtcr, "cr1", s7_D_pce, "", 2, 1, 0},
402 {s7_D_mtcr, "cr1", s7_D_cond_br, "", 1, 0, 1},
403 {s7_D_mtcr, "cr1", s7_D_cond_mv, "", 1, 0, 1},
404 /* Status regiser. */
405 {s7_D_mtcr, "cr0", s7_D_all_insn, "", 5, 4, 0},
407 {s7_D_mtcr, "cr4", s7_D_all_insn, "", 6, 5, 0},
408 /* EntryHi/EntryLo register. */
409 {s7_D_mftlb, "", s7_D_mtptlb, "", 1, 1, 1},
410 {s7_D_mftlb, "", s7_D_mtrtlb, "", 1, 1, 1},
411 {s7_D_mftlb, "", s7_D_stlb, "", 1, 1,1},
412 {s7_D_mftlb, "", s7_D_mfcr, "cr11", 1, 1, 1},
413 {s7_D_mftlb, "", s7_D_mfcr, "cr12", 1, 1, 1},
414 /* Index register. */
415 {s7_D_stlb, "", s7_D_mtptlb, "", 1, 1, 1},
416 {s7_D_stlb, "", s7_D_mftlb, "", 1, 1, 1},
417 {s7_D_stlb, "", s7_D_mfcr, "cr8", 2, 2, 1},
419 {s7_D_cached, "", s7_D_ldst, "", 1, 1, 0},
420 {s7_D_cached, "", s7_D_ldcombine, "", 1, 1, 0},
421 {s7_D_cachei, "", s7_D_all_insn, "", 5, 4, 0},
423 {s7_D_ldcombine, "", s7_D_mfsr, "sr1", 3, 3, 1},
428 /* Used to contain constructed error messages. */
429 static char s7_err_msg[255];
430 static int s7_fix_data_dependency = 0;
431 static int s7_warn_fix_data_dependency = 1;
433 static int s7_in_my_get_expression = 0;
435 /* Default, pop warning message when using r1. */
436 static int s7_nor1 = 1;
438 /* Default will do instruction relax, -O0 will set s7_g_opt = 0. */
439 static unsigned int s7_g_opt = 1;
441 /* The size of the small data section. */
442 static unsigned int s7_g_switch_value = 8;
444 static segT s7_pdr_seg;
448 char name[s7_INSN_NAME_LEN];
449 unsigned long instruction;
450 unsigned long relax_inst;
453 enum score_insn_type type;
454 char str[s7_MAX_LITERAL_POOL_SIZE];
457 char reg[s7_INSN_NAME_LEN];
460 bfd_reloc_code_real_type type;
465 static struct s7_score_it s7_inst;
470 unsigned long reg_mask;
471 unsigned long reg_offset;
472 unsigned long fpreg_mask;
474 unsigned long frame_offset;
475 unsigned long frame_reg;
476 unsigned long pc_reg;
478 static s7_procS s7_cur_proc;
479 static s7_procS *s7_cur_proc_ptr;
480 static int s7_numprocs;
482 /* Structure for a hash table entry for a register. */
489 static const struct s7_reg_entry s7_score_rn_table[] =
491 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
492 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
493 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
494 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
495 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
496 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
497 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
498 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
502 static const struct s7_reg_entry s7_score_srn_table[] =
504 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
508 static const struct s7_reg_entry s7_score_crn_table[] =
510 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
511 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
512 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
513 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
514 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
515 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
516 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
517 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
523 const struct s7_reg_entry *names;
525 struct hash_control *htab;
526 const char *expected;
529 static struct s7_reg_map s7_all_reg_maps[] =
531 {s7_score_rn_table, 31, NULL, N_("S+core register expected")},
532 {s7_score_srn_table, 2, NULL, N_("S+core special-register expected")},
533 {s7_score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
536 static struct hash_control *s7_score_ops_hsh = NULL;
537 static struct hash_control *s7_dependency_insn_hsh = NULL;
540 struct s7_datafield_range
547 static struct s7_datafield_range s7_score_df_range[] =
549 {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */
550 {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */
551 {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */
552 {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */
553 {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
554 {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
555 {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */
556 {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */
557 {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */
558 {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */
559 {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
560 {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */
561 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */
562 {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
563 {_IMM20, 20, {0, (1 << 20) - 1}},
564 {_IMM25, 25, {0, (1 << 25) - 1}},
565 {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */
566 {_DISP11div2, 11, {0, 0}},
567 {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */
568 {_DISP24div2, 24, {0, 0}},
569 {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}},
570 {_VALUE_HI16, 16, {0, (1 << 16) - 1}},
571 {_VALUE_LO16, 16, {0, (1 << 16) - 1}},
572 {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}},
573 {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
574 {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */
575 {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */
576 {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
577 {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */
578 {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */
579 {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */
580 {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */
581 {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */
582 {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */
583 {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */
584 {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */
585 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
586 {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
587 {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */
588 {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */
589 {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */
590 {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */
591 {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
592 {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
593 {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
599 /* Instruction name. */
600 const char *template_name;
602 /* Instruction Opcode. */
605 /* Instruction bit mask. */
608 /* Relax instruction opcode. 0x8000 imply no relaxation. */
611 /* Instruction type. */
612 enum score_insn_type type;
614 /* Function to call to parse args. */
615 void (*parms) (char *);
618 static const struct s7_asm_opcode s7_score_ldst_insns[] =
620 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, s7_do_ldst_insn},
621 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
622 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
623 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, s7_do_ldst_insn},
624 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
625 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
626 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn},
627 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
628 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
629 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn},
630 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
631 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
632 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, s7_do_ldst_insn},
633 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
634 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
635 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, s7_do_ldst_insn},
636 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
637 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
638 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, s7_do_ldst_insn},
639 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
640 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
641 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, s7_do_ldst_insn},
642 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
643 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
646 static const struct s7_asm_opcode s7_score_insns[] =
648 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
649 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
650 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
651 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, s7_do_rdrsrs},
652 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
653 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
654 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, s7_do_rdrsrs},
655 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
656 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
657 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16},
658 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16},
659 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14},
660 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14},
661 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, s7_do16_rdrs},
662 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, s7_do16_rdrs},
663 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4},
664 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16},
665 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16},
666 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14},
667 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14},
668 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
669 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, s7_do_rdrsrs},
670 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
671 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
672 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
673 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
674 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
675 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
676 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, s7_do16_rdrs},
677 {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
678 {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
679 {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
680 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
681 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
682 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
683 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, s7_do16_branch},
684 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, s7_do16_branch},
685 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, s7_do16_branch},
686 {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
687 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
688 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, s7_do16_branch},
689 {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
690 {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
691 {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
692 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
693 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
694 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
695 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, s7_do16_branch},
696 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, s7_do16_branch},
697 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, s7_do16_branch},
698 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, s7_do_rdrsi5},
699 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
700 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, s7_do_rdrsi5},
701 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, s7_do_xrsi5},
702 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, s7_do_rdrsi5},
703 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, s7_do16_rdi5},
704 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, s7_do16_rdi5},
705 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, s7_do16_rdi5},
706 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, s7_do16_rdi5},
707 {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
708 {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
709 {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
710 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
711 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
712 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
713 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
714 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, s7_do16_branch},
715 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, s7_do16_branch},
716 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, s7_do16_branch},
717 {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
718 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
719 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, s7_do16_branch},
720 {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
721 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
722 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, s7_do16_branch},
723 {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
724 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
725 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, s7_do16_branch},
726 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, s7_do_rs},
727 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, s7_do_rs},
728 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, s7_do_rs},
729 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, s7_do_rs},
730 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, s7_do_rs},
731 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, s7_do_rs},
732 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, s7_do_rs},
733 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, s7_do_rs},
734 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, s7_do_rs},
735 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, s7_do_rs},
736 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, s7_do_rs},
737 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, s7_do_rs},
738 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, s7_do_rs},
739 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, s7_do_rs},
740 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, s7_do_rs},
741 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, s7_do_rs},
742 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, s7_do_rs},
743 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, s7_do_rs},
744 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, s7_do_rs},
745 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, s7_do_rs},
746 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, s7_do_rs},
747 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, s7_do_rs},
748 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, s7_do_rs},
749 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, s7_do_rs},
750 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, s7_do_rs},
751 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, s7_do_rs},
752 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, s7_do_rs},
753 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, s7_do_rs},
754 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, s7_do_rs},
755 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, s7_do_rs},
756 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, s7_do_rs},
757 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, s7_do_rs},
758 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, s7_do16_xrs},
759 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, s7_do16_xrs},
760 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, s7_do16_xrs},
761 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, s7_do16_xrs},
762 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, s7_do16_xrs},
763 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, s7_do16_xrs},
764 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, s7_do16_xrs},
765 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, s7_do16_xrs},
766 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, s7_do16_xrs},
767 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, s7_do16_xrs},
768 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, s7_do16_xrs},
769 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, s7_do16_xrs},
770 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, s7_do16_xrs},
771 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, s7_do16_xrs},
772 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, s7_do16_xrs},
773 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, s7_do16_xrs},
774 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, s7_do16_xrs},
775 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, s7_do16_xrs},
776 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, s7_do16_xrs},
777 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, s7_do16_xrs},
778 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, s7_do16_xrs},
779 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, s7_do16_xrs},
780 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, s7_do16_xrs},
781 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, s7_do16_xrs},
782 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, s7_do16_xrs},
783 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, s7_do16_xrs},
784 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, s7_do16_xrs},
785 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, s7_do16_xrs},
786 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, s7_do16_xrs},
787 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, s7_do16_xrs},
788 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, s7_do16_xrs},
789 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, s7_do16_xrs},
790 {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
791 {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
792 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
793 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
794 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, s7_do16_branch},
795 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, s7_do16_branch},
796 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, s7_do16_branch},
797 {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
798 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s7_do_cache},
799 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s7_do_ceinst},
800 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
801 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
802 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
803 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, s7_do_rsrs},
804 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
805 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
806 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
807 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
808 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, s7_do16_rdrs},
809 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
810 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
811 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
812 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
813 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
814 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
815 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
816 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
817 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
818 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
819 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
820 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
821 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump},
822 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, s7_do16_jump},
823 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, s7_do16_jump},
824 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump},
825 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, s7_do16_ldst_insn},
826 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
827 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s7_do_ldst_atomic},
828 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s7_do_ldst_unalign},
829 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign},
830 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign},
831 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
832 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
833 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
834 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, s7_do16_ldst_insn},
835 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
836 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, s7_do_rdsi16},
837 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s7_do_rdi16},
838 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, s7_do16_ldst_imm_insn},
839 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, s7_do16_ldst_insn},
840 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
841 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
842 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, s7_do16_rs},
843 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
844 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, s7_do16_rdrs},
845 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
846 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
847 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, s7_do16_rdrs},
848 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
849 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
850 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, s7_do16_rdrs},
851 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
852 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, s7_do16_rdrs},
853 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
854 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
855 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
856 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
857 {"mazh.f!", 0x1009, 0x700f, 0x38000383, Rd_Rs, s7_do16_rdrs},
858 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
859 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
860 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, s7_do16_rdrs},
861 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
862 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, s7_do16_rs},
863 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
864 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s7_do_rdsrs},
865 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
866 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
867 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
868 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
869 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
870 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
871 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
872 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, s7_do16_hrdrs},
873 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
874 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, s7_do16_rdhrs},
875 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
876 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, s7_do16_rdrs},
877 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
878 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
879 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, s7_do16_rdrs},
880 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
881 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
882 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, s7_do16_rdrs},
883 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
884 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, s7_do16_rdrs},
885 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
886 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
887 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
888 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, s7_do16_rdrs},
889 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
890 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
891 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, s7_do16_rdrs},
892 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, s7_do16_rs},
893 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
894 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
895 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, s7_do16_rs},
896 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
897 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s7_do_rdsrs},
898 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
899 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
900 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
901 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
902 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
903 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
904 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
905 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, s7_do16_rdrs},
906 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, s7_do16_rdrs},
907 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
908 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
909 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
910 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
911 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
912 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
913 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
914 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
915 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
916 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
917 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
918 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
919 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
920 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
921 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, s7_do_rdrs},
922 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, s7_do16_mv_rdrs},
923 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s7_do_rdxrs},
924 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, s7_do_rdxrs},
925 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, s7_do16_rdrs},
926 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s7_do_empty},
927 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
928 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, s7_do_rdrs},
929 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, s7_do_empty},
930 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, s7_do16_rdrs},
931 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
932 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, s7_do_rdrsrs},
933 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
934 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
935 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
936 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
937 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
938 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
939 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, s7_do16_rdrs},
940 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
941 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, s7_do16_push_pop},
942 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, s7_do16_push_pop},
943 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
944 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
945 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
946 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
947 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
948 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
949 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
950 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
951 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
952 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
953 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
954 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
955 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
956 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, s7_do16_ldst_insn},
957 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
958 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s7_do_ldst_atomic},
959 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign},
960 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign},
961 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s7_do_ldst_unalign},
962 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, s7_do_xi5x},
963 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, s7_do16_xi5},
964 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, s7_do16_ldst_insn},
965 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
966 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
967 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
968 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, s7_do_rdrsrs},
969 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
970 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
971 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, s7_do_rdrsi5},
972 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, s7_do16_rdrs},
973 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, s7_do16_rdi5},
974 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
975 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, s7_do_rdrsrs},
976 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
977 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, s7_do_rdrsrs},
978 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
979 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, s7_do_rdrsi5},
980 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
981 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
982 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, s7_do16_rdrs},
983 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, s7_do16_rdrs},
984 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, s7_do16_rdi5},
985 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
986 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
987 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
988 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
989 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, s7_do_rdrsrs},
990 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
991 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
992 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
993 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, s7_do16_rdrs},
994 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4},
995 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, s7_do16_ldst_insn},
996 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
997 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s7_do_i15},
998 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, s7_do_empty},
999 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, s7_do_empty},
1000 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, s7_do_empty},
1001 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, s7_do_empty},
1002 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, s7_do_empty},
1003 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, s7_do_empty},
1004 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, s7_do_empty},
1005 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, s7_do_empty},
1006 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, s7_do_empty},
1007 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, s7_do_empty},
1008 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, s7_do_empty},
1009 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, s7_do_empty},
1010 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, s7_do_empty},
1011 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, s7_do_empty},
1012 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, s7_do_empty},
1013 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, s7_do_empty},
1014 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, s7_do_empty},
1015 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1016 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1017 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1018 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1019 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, s7_do_empty},
1020 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, s7_do_empty},
1021 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, s7_do_empty},
1022 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, s7_do_empty},
1023 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, s7_do_empty},
1024 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, s7_do_empty},
1025 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, s7_do_empty},
1026 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, s7_do_empty},
1027 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, s7_do_empty},
1028 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1029 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1030 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1031 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1032 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1033 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1034 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1035 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1036 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1037 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1038 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1039 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1040 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1041 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1042 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1043 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, s7_do_empty},
1044 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, s7_do_empty},
1045 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, s7_do_empty},
1046 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, s7_do_empty},
1047 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, s7_do_empty},
1048 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, s7_do_empty},
1049 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
1050 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, s7_do_rdrsrs},
1051 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, s7_do16_rdrs},
1052 /* Macro instruction. */
1053 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_li_rdi32},
1054 /* la reg, imm32 -->(1) ldi reg, simm16
1055 (2) ldis reg, %HI(imm32)
1058 la reg, symbol -->(1) lis reg, %HI(imm32)
1059 ori reg, %LO(imm32) */
1060 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_la_rdi32},
1061 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1062 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1063 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1064 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1065 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1066 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1067 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1068 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1069 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1070 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1071 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label},
1072 {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, s7_do_macro_ldst_label},
1073 {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, s7_do_macro_ldst_label},
1074 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label},
1075 {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, s7_do_macro_ldst_label},
1076 {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, s7_do_macro_ldst_label},
1077 {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, s7_do_macro_ldst_label},
1078 {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, s7_do_macro_ldst_label},
1079 /* Assembler use internal. */
1080 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s7_do_macro_rdi32hi},
1081 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_macro_rdi32lo},
1082 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, s7_do_rdi16_pic},
1083 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_s_pic},
1084 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_u_pic},
1085 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s7_do_lw_pic},
1088 #define s7_SCORE5_PIPELINE 5
1089 #define s7_SCORE7_PIPELINE 7
1091 static int s7_university_version = 0;
1092 static int s7_vector_size = s7_SCORE7_PIPELINE;
1093 static struct s7_score_it s7_dependency_vector[s7_SCORE7_PIPELINE];
1095 static int s7_score7d = 1;
1100 s7_end_of_line (char *str)
1102 int retval = s7_SUCCESS;
1104 s7_skip_whitespace (str);
1107 retval = (int) s7_FAIL;
1110 s7_inst.error = s7_BAD_GARBAGE;
1117 s7_score_reg_parse (char **ccp, struct hash_control *htab)
1122 struct s7_reg_entry *reg;
1125 if (!ISALPHA (*p) || !is_name_beginner (*p))
1126 return (int) s7_FAIL;
1130 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1134 reg = (struct s7_reg_entry *) hash_find (htab, start);
1142 return (int) s7_FAIL;
1145 /* If shift <= 0, only return reg. */
1147 s7_reg_required_here (char **str, int shift, enum s7_score_reg_type reg_type)
1149 static char buff[s7_MAX_LITERAL_POOL_SIZE];
1150 int reg = (int) s7_FAIL;
1153 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[reg_type].htab)) != (int) s7_FAIL)
1155 if (reg_type == s7_REG_TYPE_SCORE)
1157 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
1159 as_warn (_("Using temp register(r1)"));
1165 if (reg_type == s7_REG_TYPE_SCORE_CR)
1166 strcpy (s7_inst.reg, s7_score_crn_table[reg].name);
1167 else if (reg_type == s7_REG_TYPE_SCORE_SR)
1168 strcpy (s7_inst.reg, s7_score_srn_table[reg].name);
1170 strcpy (s7_inst.reg, "");
1172 s7_inst.instruction |= reg << shift;
1178 sprintf (buff, _("register expected, not '%.100s'"), start);
1179 s7_inst.error = buff;
1186 s7_skip_past_comma (char **str)
1192 while ((c = *p) == ' ' || c == ',')
1195 if (c == ',' && comma++)
1197 s7_inst.error = s7_BAD_SKIP_COMMA;
1198 return (int) s7_FAIL;
1202 if ((c == '\0') || (comma == 0))
1204 s7_inst.error = s7_BAD_SKIP_COMMA;
1205 return (int) s7_FAIL;
1209 return comma ? s7_SUCCESS : (int) s7_FAIL;
1213 s7_do_rdrsrs (char *str)
1215 s7_skip_whitespace (str);
1217 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1218 || s7_skip_past_comma (&str) == (int) s7_FAIL
1219 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1220 || s7_skip_past_comma (&str) == (int) s7_FAIL
1221 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1222 || s7_end_of_line (str) == (int) s7_FAIL)
1228 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
1229 && (((s7_inst.instruction >> 10) & 0x10) == 0)
1230 && (((s7_inst.instruction >> 20) & 0x10) == 0)
1231 && (s7_inst.relax_inst != 0x8000)
1232 && (((s7_inst.instruction >> 20) & 0xf) == ((s7_inst.instruction >> 15) & 0xf)))
1234 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4)
1235 | (((s7_inst.instruction >> 15) & 0xf) << 8);
1236 s7_inst.relax_size = 2;
1240 s7_inst.relax_inst = 0x8000;
1246 s7_walk_no_bignums (symbolS * sp)
1248 if (symbol_get_value_expression (sp)->X_op == O_big)
1251 if (symbol_get_value_expression (sp)->X_add_symbol)
1252 return (s7_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1253 || (symbol_get_value_expression (sp)->X_op_symbol
1254 && s7_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1260 s7_my_get_expression (expressionS * ep, char **str)
1264 save_in = input_line_pointer;
1265 input_line_pointer = *str;
1266 s7_in_my_get_expression = 1;
1268 (void) expression (ep);
1269 s7_in_my_get_expression = 0;
1271 if (ep->X_op == O_illegal)
1273 *str = input_line_pointer;
1274 input_line_pointer = save_in;
1275 s7_inst.error = _("illegal expression");
1276 return (int) s7_FAIL;
1278 /* Get rid of any bignums now, so that we don't generate an error for which
1279 we can't establish a line number later on. Big numbers are never valid
1280 in instructions, which is where this routine is always called. */
1281 if (ep->X_op == O_big
1282 || (ep->X_add_symbol
1283 && (s7_walk_no_bignums (ep->X_add_symbol)
1284 || (ep->X_op_symbol && s7_walk_no_bignums (ep->X_op_symbol)))))
1286 s7_inst.error = _("invalid constant");
1287 *str = input_line_pointer;
1288 input_line_pointer = save_in;
1289 return (int) s7_FAIL;
1292 if ((ep->X_add_symbol != NULL)
1293 && (s7_inst.type != PC_DISP19div2)
1294 && (s7_inst.type != PC_DISP8div2)
1295 && (s7_inst.type != PC_DISP24div2)
1296 && (s7_inst.type != PC_DISP11div2)
1297 && (s7_inst.type != Insn_Type_SYN)
1298 && (s7_inst.type != Rd_rvalueRs_SI15)
1299 && (s7_inst.type != Rd_lvalueRs_SI15)
1300 && (s7_inst.type != Insn_internal))
1302 s7_inst.error = s7_BAD_ARGS;
1303 *str = input_line_pointer;
1304 input_line_pointer = save_in;
1305 return (int) s7_FAIL;
1308 *str = input_line_pointer;
1309 input_line_pointer = save_in;
1313 /* Check if an immediate is valid. If so, convert it to the right format. */
1315 static bfd_signed_vma
1316 s7_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
1322 int val_hi = ((val & 0xffff0000) >> 16);
1324 if (s7_score_df_range[data_type].range[0] <= val_hi
1325 && val_hi <= s7_score_df_range[data_type].range[1])
1332 int val_lo = (val & 0xffff);
1334 if (s7_score_df_range[data_type].range[0] <= val_lo
1335 && val_lo <= s7_score_df_range[data_type].range[1])
1343 if (!(val >= -0x800 && val <= 0xfff))
1345 return (int) s7_FAIL;
1350 if (!(val >= -2048 && val <= 2047))
1352 return (int) s7_FAIL;
1362 if (!(val >= -0x2000 && val <= 0x3fff))
1364 return (int) s7_FAIL;
1369 if (!(val >= -8192 && val <= 8191))
1371 return (int) s7_FAIL;
1381 if (!(val >= -0x4000 && val <= 0x7fff))
1383 return (int) s7_FAIL;
1388 if (!(val >= -16384 && val <= 16383))
1390 return (int) s7_FAIL;
1400 if (!(val >= -0x8000 && val <= 0xffff))
1402 return (int) s7_FAIL;
1407 if (!(val >= -32768 && val <= 32767))
1409 return (int) s7_FAIL;
1419 if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1421 return (int) s7_FAIL;
1426 if (!(val >= -32767 && val <= 32768))
1428 return (int) s7_FAIL;
1437 if (val >= 0 && val <= 0xffffffff)
1443 return (int) s7_FAIL;
1447 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1450 if (s7_score_df_range[data_type].range[0] <= val
1451 && val <= s7_score_df_range[data_type].range[1])
1457 return (int) s7_FAIL;
1461 s7_data_op2 (char **str, int shift, enum score_data_type data_type)
1464 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
1469 s7_skip_whitespace (*str);
1470 s7_inst.error = NULL;
1473 /* Set hex_p to zero. */
1476 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1478 data_exp[cnt] = *dataptr;
1483 data_exp[cnt] = '\0';
1484 pp = (char *)&data_exp;
1486 if (*dataptr == '|') /* process PCE */
1488 if (s7_my_get_expression (&s7_inst.reloc.exp, &pp) == (int) s7_FAIL)
1489 return (int) s7_FAIL;
1490 s7_end_of_line (pp);
1491 if (s7_inst.error != 0)
1492 return (int) s7_FAIL; /* to ouptut_inst to printf out the error */
1495 else /* process 16 bit */
1497 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
1499 return (int) s7_FAIL;
1502 dataptr = (char *) data_exp;
1503 for (; *dataptr != '\0'; dataptr++)
1505 *dataptr = TOLOWER (*dataptr);
1506 if (*dataptr == '!' || *dataptr == ' ')
1509 dataptr = (char *) data_exp;
1511 if ((dataptr != NULL)
1512 && (((strstr (dataptr, "0x")) != NULL)
1513 || ((strstr (dataptr, "0X")) != NULL)))
1516 if ((data_type != _SIMM16_LA)
1517 && (data_type != _VALUE_HI16)
1518 && (data_type != _VALUE_LO16)
1519 && (data_type != _IMM16)
1520 && (data_type != _IMM15)
1521 && (data_type != _IMM14)
1522 && (data_type != _IMM4)
1523 && (data_type != _IMM5)
1524 && (data_type != _IMM8)
1525 && (data_type != _IMM5_RSHIFT_1)
1526 && (data_type != _IMM5_RSHIFT_2)
1527 && (data_type != _SIMM14)
1528 && (data_type != _SIMM16)
1529 && (data_type != _SIMM14_NEG)
1530 && (data_type != _SIMM16_NEG)
1531 && (data_type != _IMM10_RSHIFT_2)
1532 && (data_type != _GP_IMM15))
1538 if ((s7_inst.reloc.exp.X_add_number == 0)
1539 /* for "addi r0,-((((((32*4)+4)+4)+4)+4)&0xf)". */
1540 && (s7_inst.type != Rd_SI16)
1541 && (s7_inst.type != Insn_Type_SYN)
1542 && (s7_inst.type != Rd_rvalueRs_SI15)
1543 && (s7_inst.type != Rd_lvalueRs_SI15)
1544 && (s7_inst.type != Insn_internal)
1545 && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1546 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1547 || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1548 || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1550 s7_inst.error = s7_BAD_ARGS;
1551 return (int) s7_FAIL;
1555 if ((s7_inst.reloc.exp.X_add_symbol)
1556 && ((data_type == _SIMM16)
1557 || (data_type == _SIMM16_NEG)
1558 || (data_type == _IMM16_NEG)
1559 || (data_type == _SIMM14)
1560 || (data_type == _SIMM14_NEG)
1561 || (data_type == _IMM5)
1562 || (data_type == _IMM14)
1563 || (data_type == _IMM20)
1564 || (data_type == _IMM16)
1565 || (data_type == _IMM15)
1566 || (data_type == _IMM4)))
1568 s7_inst.error = s7_BAD_ARGS;
1569 return (int) s7_FAIL;
1572 if (s7_inst.reloc.exp.X_add_symbol)
1577 return (int) s7_FAIL;
1579 s7_inst.reloc.type = BFD_RELOC_HI16_S;
1580 s7_inst.reloc.pc_rel = 0;
1583 s7_inst.reloc.type = BFD_RELOC_LO16;
1584 s7_inst.reloc.pc_rel = 0;
1587 s7_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1588 s7_inst.reloc.pc_rel = 0;
1591 case _IMM16_LO16_pic:
1592 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1593 s7_inst.reloc.pc_rel = 0;
1596 s7_inst.reloc.type = BFD_RELOC_32;
1597 s7_inst.reloc.pc_rel = 0;
1603 if (data_type == _IMM16_pic)
1605 s7_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1606 s7_inst.reloc.pc_rel = 0;
1609 if (data_type == _SIMM16_LA && s7_inst.reloc.exp.X_unsigned == 1)
1611 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
1612 if (value == (int) s7_FAIL) /* for advance to check if this is ldis */
1613 if ((s7_inst.reloc.exp.X_add_number & 0xffff) == 0)
1615 s7_inst.instruction |= 0x8000000;
1616 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1622 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
1625 if (value == (int) s7_FAIL)
1627 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1629 sprintf (s7_err_msg,
1630 _("invalid constant: %d bit expression not in range %d..%d"),
1631 s7_score_df_range[data_type].bits,
1632 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
1636 sprintf (s7_err_msg,
1637 _("invalid constant: %d bit expression not in range %d..%d"),
1638 s7_score_df_range[data_type].bits,
1639 -s7_score_df_range[data_type].range[1], -s7_score_df_range[data_type].range[0]);
1642 s7_inst.error = s7_err_msg;
1643 return (int) s7_FAIL;
1646 if ((s7_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1648 value &= (1 << s7_score_df_range[data_type].bits) - 1;
1651 s7_inst.instruction |= value << shift;
1654 if ((s7_inst.instruction & 0x3e000000) == 0x30000000)
1656 if ((((s7_inst.instruction >> 20) & 0x1F) != 0)
1657 && (((s7_inst.instruction >> 20) & 0x1F) != 1)
1658 && (((s7_inst.instruction >> 20) & 0x1F) != 2)
1659 && (((s7_inst.instruction >> 20) & 0x1F) != 3)
1660 && (((s7_inst.instruction >> 20) & 0x1F) != 4)
1661 && (((s7_inst.instruction >> 20) & 0x1F) != 8)
1662 && (((s7_inst.instruction >> 20) & 0x1F) != 9)
1663 && (((s7_inst.instruction >> 20) & 0x1F) != 0xa)
1664 && (((s7_inst.instruction >> 20) & 0x1F) != 0xb)
1665 && (((s7_inst.instruction >> 20) & 0x1F) != 0xc)
1666 && (((s7_inst.instruction >> 20) & 0x1F) != 0xd)
1667 && (((s7_inst.instruction >> 20) & 0x1F) != 0xe)
1668 && (((s7_inst.instruction >> 20) & 0x1F) != 0x10)
1669 && (((s7_inst.instruction >> 20) & 0x1F) != 0x11)
1670 && (((s7_inst.instruction >> 20) & 0x1F) != 0x18)
1671 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1A)
1672 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1B)
1673 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1d)
1674 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1e)
1675 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1f))
1677 s7_inst.error = _("invalid constant: bit expression not defined");
1678 return (int) s7_FAIL;
1685 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1688 s7_do_rdsi16 (char *str)
1690 s7_skip_whitespace (str);
1692 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1693 || s7_skip_past_comma (&str) == (int) s7_FAIL
1694 || s7_data_op2 (&str, 1, _SIMM16) == (int) s7_FAIL
1695 || s7_end_of_line (str) == (int) s7_FAIL)
1699 if ((s7_inst.instruction & 0x20c0000) == 0x20c0000)
1701 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10) || ((s7_inst.instruction & 0x1fe00) != 0))
1703 s7_inst.relax_inst = 0x8000;
1707 s7_inst.relax_inst |= (s7_inst.instruction >> 1) & 0xff;
1708 s7_inst.relax_inst |= (((s7_inst.instruction >> 20) & 0xf) << 8);
1709 s7_inst.relax_size = 2;
1712 else if (((s7_inst.instruction >> 20) & 0x10) == 0x10)
1714 s7_inst.relax_inst = 0x8000;
1718 /* Handle subi/subi.c. */
1721 s7_do_sub_rdsi16 (char *str)
1723 s7_skip_whitespace (str);
1725 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1726 && s7_skip_past_comma (&str) != (int) s7_FAIL
1727 && s7_data_op2 (&str, 1, _SIMM16_NEG) != (int) s7_FAIL)
1728 s7_end_of_line (str);
1732 /* Handle addri/addri.c. */
1735 s7_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1737 s7_skip_whitespace (str);
1739 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1740 && s7_skip_past_comma (&str) != (int) s7_FAIL
1741 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1742 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1743 s7_data_op2 (&str, 1, _SIMM14);
1746 /* Handle subri.c/subri. */
1749 s7_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1751 s7_skip_whitespace (str);
1753 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1754 && s7_skip_past_comma (&str) != (int) s7_FAIL
1755 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1756 && s7_skip_past_comma (&str) != (int) s7_FAIL
1757 && s7_data_op2 (&str, 1, _SIMM14_NEG) != (int) s7_FAIL)
1758 s7_end_of_line (str);
1761 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1764 s7_do_rdrsi5 (char *str) /* 0~((2^14)-1) */
1766 s7_skip_whitespace (str);
1768 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1769 || s7_skip_past_comma (&str) == (int) s7_FAIL
1770 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1771 || s7_skip_past_comma (&str) == (int) s7_FAIL
1772 || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
1773 || s7_end_of_line (str) == (int) s7_FAIL)
1776 if ((((s7_inst.instruction >> 20) & 0x1f) == ((s7_inst.instruction >> 15) & 0x1f))
1777 && (s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1779 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1780 s7_inst.relax_size = 2;
1783 s7_inst.relax_inst = 0x8000;
1786 /* Handle andri/orri/andri.c/orri.c. */
1789 s7_do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1791 s7_skip_whitespace (str);
1793 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1794 && s7_skip_past_comma (&str) != (int) s7_FAIL
1795 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1796 && s7_skip_past_comma (&str) != (int) s7_FAIL
1797 && s7_data_op2 (&str, 1, _IMM14) != (int) s7_FAIL)
1798 s7_end_of_line (str);
1801 /* Handle bittst.c. */
1804 s7_do_xrsi5 (char *str)
1806 s7_skip_whitespace (str);
1808 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1809 || s7_skip_past_comma (&str) == (int) s7_FAIL
1810 || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
1811 || s7_end_of_line (str) == (int) s7_FAIL)
1814 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1816 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1817 s7_inst.relax_size = 2;
1820 s7_inst.relax_inst = 0x8000;
1823 /* Handle addis/andi/ori/andis/oris/ldis. */
1826 s7_do_rdi16 (char *str)
1828 s7_skip_whitespace (str);
1830 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1831 || s7_skip_past_comma (&str) == (int) s7_FAIL
1832 || s7_data_op2 (&str, 1, _IMM16) == (int) s7_FAIL
1833 || s7_end_of_line (str) == (int) s7_FAIL)
1838 s7_do_macro_rdi32hi (char *str)
1840 s7_skip_whitespace (str);
1842 /* Do not handle s7_end_of_line(). */
1843 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1844 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1845 s7_data_op2 (&str, 1, _VALUE_HI16);
1849 s7_do_macro_rdi32lo (char *str)
1851 s7_skip_whitespace (str);
1853 /* Do not handle s7_end_of_line(). */
1854 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1855 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1856 s7_data_op2 (&str, 1, _VALUE_LO16);
1859 /* Handle ldis_pic. */
1862 s7_do_rdi16_pic (char *str)
1864 s7_skip_whitespace (str);
1866 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1867 && s7_skip_past_comma (&str) != (int) s7_FAIL
1868 && s7_data_op2 (&str, 1, _IMM16_pic) != (int) s7_FAIL)
1869 s7_end_of_line (str);
1872 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1875 s7_do_addi_s_pic (char *str)
1877 s7_skip_whitespace (str);
1879 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1880 && s7_skip_past_comma (&str) != (int) s7_FAIL
1881 && s7_data_op2 (&str, 1, _SIMM16_pic) != (int) s7_FAIL)
1882 s7_end_of_line (str);
1885 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1888 s7_do_addi_u_pic (char *str)
1890 s7_skip_whitespace (str);
1892 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1893 && s7_skip_past_comma (&str) != (int) s7_FAIL
1894 && s7_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s7_FAIL)
1895 s7_end_of_line (str);
1898 /* Handle mfceh/mfcel/mtceh/mtchl. */
1901 s7_do_rd (char *str)
1903 s7_skip_whitespace (str);
1905 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL)
1906 s7_end_of_line (str);
1910 s7_do_rs (char *str)
1912 s7_skip_whitespace (str);
1914 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1915 || s7_end_of_line (str) == (int) s7_FAIL)
1918 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1920 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8) | (((s7_inst.instruction >> 15) & 0xf) << 4);
1921 s7_inst.relax_size = 2;
1924 s7_inst.relax_inst = 0x8000;
1928 s7_do_i15 (char *str)
1930 s7_skip_whitespace (str);
1932 if (s7_data_op2 (&str, 10, _IMM15) != (int) s7_FAIL)
1933 s7_end_of_line (str);
1937 s7_do_xi5x (char *str)
1939 s7_skip_whitespace (str);
1941 if (s7_data_op2 (&str, 15, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
1944 if (s7_inst.relax_inst != 0x8000)
1946 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0x1f) << 3);
1947 s7_inst.relax_size = 2;
1952 s7_do_rdrs (char *str)
1954 s7_skip_whitespace (str);
1956 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1957 || s7_skip_past_comma (&str) == (int) s7_FAIL
1958 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1959 || s7_end_of_line (str) == (int) s7_FAIL)
1962 if (s7_inst.relax_inst != 0x8000)
1964 if (((s7_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1967 if ((((s7_inst.instruction >> 15) & 0x10) != 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1969 s7_inst.relax_inst = 0x00000001 | (((s7_inst.instruction >> 15) & 0xf) << 4)
1970 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1971 s7_inst.relax_size = 2;
1974 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && ((s7_inst.instruction >> 20) & 0x10) != 0)
1976 s7_inst.relax_inst = 0x00000002 | (((s7_inst.instruction >> 15) & 0xf) << 4)
1977 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1978 s7_inst.relax_size = 2;
1980 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1982 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1983 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1984 s7_inst.relax_size = 2;
1988 s7_inst.relax_inst = 0x8000;
1991 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1993 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1994 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1995 s7_inst.relax_size = 2;
1999 s7_inst.relax_inst = 0x8000;
2004 /* Handle mfcr/mtcr. */
2006 s7_do_rdcrs (char *str)
2008 s7_skip_whitespace (str);
2010 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2011 && s7_skip_past_comma (&str) != (int) s7_FAIL
2012 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) != (int) s7_FAIL)
2013 s7_end_of_line (str);
2016 /* Handle mfsr/mtsr. */
2019 s7_do_rdsrs (char *str)
2021 s7_skip_whitespace (str);
2024 if ((s7_inst.instruction & 0xff) == 0x50)
2026 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2027 && s7_skip_past_comma (&str) != (int) s7_FAIL
2028 && s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR) != (int) s7_FAIL)
2029 s7_end_of_line (str);
2033 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2034 && s7_skip_past_comma (&str) != (int) s7_FAIL)
2035 s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR);
2042 s7_do_rdxrs (char *str)
2044 s7_skip_whitespace (str);
2046 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2047 || s7_skip_past_comma (&str) == (int) s7_FAIL
2048 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2049 || s7_end_of_line (str) == (int) s7_FAIL)
2052 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 10) & 0x10) == 0)
2053 && (((s7_inst.instruction >> 20) & 0x10) == 0))
2055 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 20) & 0xf) << 8);
2056 s7_inst.relax_size = 2;
2059 s7_inst.relax_inst = 0x8000;
2062 /* Handle cmp.c/cmp<cond>. */
2064 s7_do_rsrs (char *str)
2066 s7_skip_whitespace (str);
2068 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2069 || s7_skip_past_comma (&str) == (int) s7_FAIL
2070 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2071 || s7_end_of_line (str) == (int) s7_FAIL)
2074 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 20) & 0x1f) == 3)
2075 && (((s7_inst.instruction >> 10) & 0x10) == 0) && (((s7_inst.instruction >> 15) & 0x10) == 0))
2077 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 15) & 0xf) << 8);
2078 s7_inst.relax_size = 2;
2081 s7_inst.relax_inst = 0x8000;
2085 s7_do_ceinst (char *str)
2090 s7_skip_whitespace (str);
2092 if (s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL
2093 || s7_skip_past_comma (&str) == (int) s7_FAIL
2094 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2095 || s7_skip_past_comma (&str) == (int) s7_FAIL
2096 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2097 || s7_skip_past_comma (&str) == (int) s7_FAIL
2098 || s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL
2099 || s7_skip_past_comma (&str) == (int) s7_FAIL
2100 || s7_data_op2 (&str, 0, _IMM5) == (int) s7_FAIL
2101 || s7_end_of_line (str) == (int) s7_FAIL)
2108 if (s7_data_op2 (&str, 0, _IMM25) == (int) s7_FAIL)
2114 s7_reglow_required_here (char **str, int shift)
2116 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2120 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2122 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
2124 as_warn (_("Using temp register(r1)"));
2130 s7_inst.instruction |= reg << shift;
2136 /* Restore the start point, we may have got a reg of the wrong class. */
2138 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
2139 s7_inst.error = buff;
2140 return (int) s7_FAIL;
2143 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
2146 s7_do16_rdrs (char *str)
2148 s7_skip_whitespace (str);
2150 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2151 || s7_skip_past_comma (&str) == (int) s7_FAIL
2152 || s7_reglow_required_here (&str, 4) == (int) s7_FAIL
2153 || s7_end_of_line (str) == (int) s7_FAIL)
2159 if ((s7_inst.instruction & 0x700f) == 0x2003) /* cmp! */
2161 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2162 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2164 else if ((s7_inst.instruction & 0x700f) == 0x2006) /* not! */
2166 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2167 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2169 else if ((s7_inst.instruction & 0x700f) == 0x1009) /* mazh.f! */
2171 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2172 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2176 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2177 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 4) & 0xf) << 10);
2179 s7_inst.relax_size = 4;
2184 s7_do16_rs (char *str)
2188 s7_skip_whitespace (str);
2190 if ((rd = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL
2191 || s7_end_of_line (str) == (int) s7_FAIL)
2197 s7_inst.relax_inst |= rd << 20;
2198 s7_inst.relax_size = 4;
2202 /* Handle br!/brl!. */
2205 s7_do16_xrs (char *str)
2207 s7_skip_whitespace (str);
2209 if (s7_reglow_required_here (&str, 4) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2215 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 10)
2216 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2217 s7_inst.relax_size = 4;
2222 s7_reghigh_required_here (char **str, int shift)
2224 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2228 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2230 if (15 < reg && reg < 32)
2233 s7_inst.instruction |= (reg & 0xf) << shift;
2240 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
2241 s7_inst.error = buff;
2242 return (int) s7_FAIL;
2248 s7_do16_hrdrs (char *str)
2250 s7_skip_whitespace (str);
2252 if (s7_reghigh_required_here (&str, 8) != (int) s7_FAIL
2253 && s7_skip_past_comma (&str) != (int) s7_FAIL
2254 && s7_reglow_required_here (&str, 4) != (int) s7_FAIL
2255 && s7_end_of_line (str) != (int) s7_FAIL)
2257 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
2258 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2259 s7_inst.relax_size = 4;
2266 s7_do16_rdhrs (char *str)
2268 s7_skip_whitespace (str);
2270 if (s7_reglow_required_here (&str, 8) != (int) s7_FAIL
2271 && s7_skip_past_comma (&str) != (int) s7_FAIL
2272 && s7_reghigh_required_here (&str, 4) != (int) s7_FAIL
2273 && s7_end_of_line (str) != (int) s7_FAIL)
2275 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2276 | ((((s7_inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
2277 s7_inst.relax_size = 4;
2281 /* We need to be able to fix up arbitrary expressions in some statements.
2282 This is so that we can handle symbols that are an arbitrary distance from
2283 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
2284 which returns part of an address in a form which will be valid for
2285 a data instruction. We do this by pushing the expression into a symbol
2286 in the expr_section, and creating a fix for that. */
2289 s7_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
2299 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
2302 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
2309 s7_init_dependency_vector (void)
2313 for (i = 0; i < s7_vector_size; i++)
2314 memset (&s7_dependency_vector[i], '\0', sizeof (s7_dependency_vector[i]));
2319 static enum s7_insn_type_for_dependency
2320 s7_dependency_type_from_insn (char *insn_name)
2322 char name[s7_INSN_NAME_LEN];
2323 const struct s7_insn_to_dependency *tmp;
2325 strcpy (name, insn_name);
2326 tmp = (const struct s7_insn_to_dependency *) hash_find (s7_dependency_insn_hsh, name);
2331 return s7_D_all_insn;
2335 s7_check_dependency (char *pre_insn, char *pre_reg,
2336 char *cur_insn, char *cur_reg, int *warn_or_error)
2340 enum s7_insn_type_for_dependency pre_insn_type;
2341 enum s7_insn_type_for_dependency cur_insn_type;
2343 pre_insn_type = s7_dependency_type_from_insn (pre_insn);
2344 cur_insn_type = s7_dependency_type_from_insn (cur_insn);
2346 for (i = 0; i < sizeof (s7_data_dependency_table) / sizeof (s7_data_dependency_table[0]); i++)
2348 if ((pre_insn_type == s7_data_dependency_table[i].pre_insn_type)
2349 && (s7_D_all_insn == s7_data_dependency_table[i].cur_insn_type
2350 || cur_insn_type == s7_data_dependency_table[i].cur_insn_type)
2351 && (strcmp (s7_data_dependency_table[i].pre_reg, "") == 0
2352 || strcmp (s7_data_dependency_table[i].pre_reg, pre_reg) == 0)
2353 && (strcmp (s7_data_dependency_table[i].cur_reg, "") == 0
2354 || strcmp (s7_data_dependency_table[i].cur_reg, cur_reg) == 0))
2356 if (s7_vector_size == s7_SCORE5_PIPELINE)
2357 bubbles = s7_data_dependency_table[i].bubblenum_5;
2359 bubbles = s7_data_dependency_table[i].bubblenum_7;
2360 *warn_or_error = s7_data_dependency_table[i].warn_or_error;
2368 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
2369 for use in the a.out file, and stores them in the array pointed to by buf.
2370 This knows about the endian-ness of the target machine and does
2371 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
2372 2 (short) and 4 (long) Floating numbers are put out as a series of
2373 LITTLENUMS (shorts, here at least). */
2376 s7_number_to_chars (char *buf, valueT val, int n)
2378 if (target_big_endian)
2379 number_to_chars_bigendian (buf, val, n);
2381 number_to_chars_littleendian (buf, val, n);
2385 s7_build_one_frag (struct s7_score_it one_inst)
2388 int relaxable_p = s7_g_opt;
2391 /* Start a new frag if frag_now is not empty. */
2392 if (frag_now_fix () != 0)
2394 if (!frag_now->tc_frag_data.is_insn)
2395 frag_wane (frag_now);
2401 p = frag_more (one_inst.size);
2402 s7_number_to_chars (p, one_inst.instruction, one_inst.size);
2405 dwarf2_emit_insn (one_inst.size);
2408 relaxable_p &= (one_inst.relax_size != 0);
2409 relax_size = relaxable_p ? one_inst.relax_size : 0;
2411 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2412 s7_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2413 one_inst.type, 0, 0, relaxable_p),
2417 s7_number_to_chars (p, one_inst.relax_inst, relax_size);
2421 s7_handle_dependency (struct s7_score_it *theinst)
2424 int warn_or_error = 0; /* warn - 0; error - 1 */
2426 int remainder_bubbles = 0;
2427 char cur_insn[s7_INSN_NAME_LEN];
2428 char pre_insn[s7_INSN_NAME_LEN];
2429 struct s7_score_it nop_inst;
2430 struct s7_score_it pflush_inst;
2432 nop_inst.instruction = 0x0000;
2434 nop_inst.relax_inst = 0x80008000;
2435 nop_inst.relax_size = 4;
2436 nop_inst.type = NO16_OPD;
2438 pflush_inst.instruction = 0x8000800a;
2439 pflush_inst.size = 4;
2440 pflush_inst.relax_inst = 0x8000;
2441 pflush_inst.relax_size = 0;
2442 pflush_inst.type = NO_OPD;
2444 /* pflush will clear all data dependency. */
2445 if (strcmp (theinst->name, "pflush") == 0)
2447 s7_init_dependency_vector ();
2451 /* Push current instruction to s7_dependency_vector[0]. */
2452 for (i = s7_vector_size - 1; i > 0; i--)
2453 memcpy (&s7_dependency_vector[i], &s7_dependency_vector[i - 1], sizeof (s7_dependency_vector[i]));
2455 memcpy (&s7_dependency_vector[0], theinst, sizeof (s7_dependency_vector[i]));
2457 /* There is no dependency between nop and any instruction. */
2458 if (strcmp (s7_dependency_vector[0].name, "nop") == 0
2459 || strcmp (s7_dependency_vector[0].name, "nop!") == 0)
2462 /* "pce" is defined in s7_insn_to_dependency_table. */
2463 #define PCE_NAME "pce"
2465 if (s7_dependency_vector[0].type == Insn_Type_PCE)
2466 strcpy (cur_insn, PCE_NAME);
2468 strcpy (cur_insn, s7_dependency_vector[0].name);
2470 for (i = 1; i < s7_vector_size; i++)
2472 /* The element of s7_dependency_vector is NULL. */
2473 if (s7_dependency_vector[i].name[0] == '\0')
2476 if (s7_dependency_vector[i].type == Insn_Type_PCE)
2477 strcpy (pre_insn, PCE_NAME);
2479 strcpy (pre_insn, s7_dependency_vector[i].name);
2481 bubbles = s7_check_dependency (pre_insn, s7_dependency_vector[i].reg,
2482 cur_insn, s7_dependency_vector[0].reg, &warn_or_error);
2483 remainder_bubbles = bubbles - i + 1;
2485 if (remainder_bubbles > 0)
2489 if (s7_fix_data_dependency == 1)
2491 if (remainder_bubbles <= 2)
2493 if (s7_warn_fix_data_dependency)
2494 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2495 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2496 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2497 remainder_bubbles, bubbles);
2499 for (j = (s7_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2500 memcpy (&s7_dependency_vector[j], &s7_dependency_vector[j - remainder_bubbles],
2501 sizeof (s7_dependency_vector[j]));
2503 for (j = 1; j <= remainder_bubbles; j++)
2505 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2507 s7_build_one_frag (nop_inst);
2512 if (s7_warn_fix_data_dependency)
2513 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2514 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2515 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2518 for (j = 1; j < s7_vector_size; j++)
2519 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2521 /* Insert pflush. */
2522 s7_build_one_frag (pflush_inst);
2529 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2530 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2531 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2532 remainder_bubbles, bubbles);
2536 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2537 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2538 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2539 remainder_bubbles, bubbles);
2546 static enum insn_class
2547 s7_get_insn_class_from_type (enum score_insn_type type)
2549 enum insn_class retval = (int) s7_FAIL;
2555 case Rd_rvalueBP_I5:
2556 case Rd_lvalueBP_I5:
2567 retval = INSN_CLASS_16;
2576 case Rd_rvalueRs_SI10:
2577 case Rd_lvalueRs_SI10:
2578 case Rd_rvalueRs_preSI12:
2579 case Rd_rvalueRs_postSI12:
2580 case Rd_lvalueRs_preSI12:
2581 case Rd_lvalueRs_postSI12:
2583 case Rd_rvalueRs_SI15:
2584 case Rd_lvalueRs_SI15:
2593 case OP5_rvalueRs_SI15:
2594 case I5_Rs_Rs_I5_OP5:
2595 case x_rvalueRs_post4:
2596 case Rd_rvalueRs_post4:
2598 case Rd_lvalueRs_post4:
2599 case x_lvalueRs_post4:
2607 retval = INSN_CLASS_32;
2610 retval = INSN_CLASS_PCE;
2613 retval = INSN_CLASS_SYN;
2622 static unsigned long
2623 s7_adjust_paritybit (unsigned long m_code, enum insn_class i_class)
2625 unsigned long result = 0;
2626 unsigned long m_code_high = 0;
2627 unsigned long m_code_low = 0;
2628 unsigned long pb_high = 0;
2629 unsigned long pb_low = 0;
2631 if (i_class == INSN_CLASS_32)
2633 pb_high = 0x80000000;
2634 pb_low = 0x00008000;
2636 else if (i_class == INSN_CLASS_16)
2641 else if (i_class == INSN_CLASS_PCE)
2644 pb_low = 0x00008000;
2646 else if (i_class == INSN_CLASS_SYN)
2648 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2649 be changed if macro instruction has been expanded. */
2650 pb_high = 0x80000000;
2651 pb_low = 0x00008000;
2658 m_code_high = m_code & 0x3fff8000;
2659 m_code_low = m_code & 0x00007fff;
2660 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2666 s7_gen_insn_frag (struct s7_score_it *part_1, struct s7_score_it *part_2)
2669 bfd_boolean pce_p = FALSE;
2670 int relaxable_p = s7_g_opt;
2672 struct s7_score_it *inst1 = part_1;
2673 struct s7_score_it *inst2 = part_2;
2674 struct s7_score_it backup_inst1;
2676 pce_p = (inst2) ? TRUE : FALSE;
2677 memcpy (&backup_inst1, inst1, sizeof (struct s7_score_it));
2679 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2682 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2683 | (inst2->instruction & 0x7FFF);
2684 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2685 if (!target_big_endian)
2687 unsigned long tmp = backup_inst1.instruction;
2688 backup_inst1.instruction = ((tmp & 0xffff) << 16)
2691 backup_inst1.relax_inst = 0x8000;
2692 backup_inst1.size = s7_INSN_SIZE;
2693 backup_inst1.relax_size = 0;
2694 backup_inst1.type = Insn_Type_PCE;
2698 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction,
2699 s7_GET_INSN_CLASS (backup_inst1.type));
2702 if (backup_inst1.relax_size != 0)
2704 enum insn_class tmp;
2706 tmp = (backup_inst1.size == s7_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2707 backup_inst1.relax_inst = s7_adjust_paritybit (backup_inst1.relax_inst, tmp);
2710 /* Check data dependency. */
2711 s7_handle_dependency (&backup_inst1);
2713 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2714 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2715 if (frag_now_fix () != 0)
2717 if (!frag_now->tc_frag_data.is_insn)
2718 frag_wane (frag_now);
2723 /* Here, we must call frag_grow in order to keep the instruction frag type is
2724 rs_machine_dependent.
2725 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2726 acturally will call frag_wane.
2727 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2731 p = frag_more (backup_inst1.size);
2732 s7_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2735 dwarf2_emit_insn (backup_inst1.size);
2738 /* Generate fixup structure. */
2741 if (inst1->reloc.type != BFD_RELOC_NONE)
2742 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2743 inst1->size, &inst1->reloc.exp,
2744 inst1->reloc.pc_rel, inst1->reloc.type);
2746 if (inst2->reloc.type != BFD_RELOC_NONE)
2747 s7_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2748 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2752 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2753 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2754 backup_inst1.size, &backup_inst1.reloc.exp,
2755 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2758 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2759 relaxable_p &= (backup_inst1.relax_size != 0);
2760 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2762 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2763 s7_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2764 backup_inst1.type, 0, 0, relaxable_p),
2765 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2768 s7_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2770 memcpy (inst1, &backup_inst1, sizeof (struct s7_score_it));
2774 s7_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2778 char *operator = insnstr;
2779 const struct s7_asm_opcode *opcode;
2781 /* Parse operator and operands. */
2782 s7_skip_whitespace (operator);
2784 for (p = operator; *p != '\0'; p++)
2785 if ((*p == ' ') || (*p == '!'))
2794 opcode = (const struct s7_asm_opcode *) hash_find (s7_score_ops_hsh, operator);
2797 memset (&s7_inst, '\0', sizeof (s7_inst));
2798 strcpy (s7_inst.str, insnstr);
2801 s7_inst.instruction = opcode->value;
2802 s7_inst.relax_inst = opcode->relax_value;
2803 s7_inst.type = opcode->type;
2804 s7_inst.size = s7_GET_INSN_SIZE (s7_inst.type);
2805 s7_inst.relax_size = 0;
2807 strcpy (s7_inst.name, opcode->template_name);
2808 strcpy (s7_inst.reg, "");
2809 s7_inst.error = NULL;
2810 s7_inst.reloc.type = BFD_RELOC_NONE;
2812 (*opcode->parms) (p);
2814 /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1. */
2815 if ((s7_inst.bwarn != -1) && (!s7_inst.error) && (gen_frag_p))
2816 s7_gen_insn_frag (&s7_inst, NULL);
2819 s7_inst.error = _("unrecognized opcode");
2823 s7_append_insn (char *str, bfd_boolean gen_frag_p)
2825 int retval = s7_SUCCESS;
2827 s7_parse_16_32_inst (str, gen_frag_p);
2831 retval = (int) s7_FAIL;
2832 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
2833 s7_inst.error = NULL;
2839 /* Handle mv! reg_high, reg_low;
2840 mv! reg_low, reg_high;
2841 mv! reg_low, reg_low; */
2843 s7_do16_mv_rdrs (char *str)
2847 char *backupstr = NULL;
2850 s7_skip_whitespace (str);
2852 if ((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2853 || s7_skip_past_comma (&str) == (int) s7_FAIL
2854 || (reg_rs = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2855 || s7_end_of_line (str) == (int) s7_FAIL)
2861 /* Case 1 : mv! or mlfh!. */
2866 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2867 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2868 s7_inst.relax_size = 4;
2872 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2874 sprintf (append_str, "mlfh! %s", backupstr);
2875 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2877 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2881 /* Case 2 : mhfl!. */
2886 s7_SET_INSN_ERROR (s7_BAD_ARGS);
2891 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2893 sprintf (append_str, "mhfl! %s", backupstr);
2894 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2897 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2905 s7_do16_rdi4 (char *str)
2907 s7_skip_whitespace (str);
2909 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2910 || s7_skip_past_comma (&str) == (int) s7_FAIL
2911 || s7_data_op2 (&str, 3, _IMM4) == (int) s7_FAIL
2912 || s7_end_of_line (str) == (int) s7_FAIL)
2918 if (((s7_inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2920 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2922 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2923 | ((1 << ((s7_inst.instruction >> 3) & 0xf)) << 1);
2924 s7_inst.relax_size = 4;
2928 s7_inst.relax_inst = 0x8000;
2933 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2935 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2936 | (((-(1 << ((s7_inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2937 s7_inst.relax_size = 4;
2941 s7_inst.relax_inst = 0x8000;
2948 s7_do16_rdi5 (char *str)
2950 s7_skip_whitespace (str);
2952 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2953 || s7_skip_past_comma (&str) == (int) s7_FAIL
2954 || s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL
2955 || s7_end_of_line (str) == (int) s7_FAIL)
2959 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2960 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 3) & 0x1f) << 10);
2961 s7_inst.relax_size = 4;
2968 s7_do16_xi5 (char *str)
2970 s7_skip_whitespace (str);
2972 if (s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2976 s7_inst.relax_inst |= (((s7_inst.instruction >> 3) & 0x1f) << 15);
2977 s7_inst.relax_size = 4;
2981 /* Check that an immediate is word alignment or half word alignment.
2982 If so, convert it to the right format. */
2985 s7_validate_immediate_align (int val, unsigned int data_type)
2987 if (data_type == _IMM5_RSHIFT_1)
2991 s7_inst.error = _("address offset must be half word alignment");
2992 return (int) s7_FAIL;
2995 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2999 s7_inst.error = _("address offset must be word alignment");
3000 return (int) s7_FAIL;
3008 s7_exp_ldst_offset (char **str, int shift, unsigned int data_type)
3015 if ((dataptr != NULL)
3016 && (((strstr (dataptr, "0x")) != NULL)
3017 || ((strstr (dataptr, "0X")) != NULL)))
3020 if ((data_type != _SIMM16_LA)
3021 && (data_type != _VALUE_HI16)
3022 && (data_type != _VALUE_LO16)
3023 && (data_type != _IMM16)
3024 && (data_type != _IMM15)
3025 && (data_type != _IMM14)
3026 && (data_type != _IMM4)
3027 && (data_type != _IMM5)
3028 && (data_type != _IMM8)
3029 && (data_type != _IMM5_RSHIFT_1)
3030 && (data_type != _IMM5_RSHIFT_2)
3031 && (data_type != _SIMM12)
3032 && (data_type != _SIMM15)
3033 && (data_type != _SIMM14_NEG)
3034 && (data_type != _IMM10_RSHIFT_2))
3040 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
3041 return (int) s7_FAIL;
3043 if (s7_inst.reloc.exp.X_op == O_constant)
3045 /* Need to check the immediate align. */
3046 int value = s7_validate_immediate_align (s7_inst.reloc.exp.X_add_number, data_type);
3048 if (value == (int) s7_FAIL)
3049 return (int) s7_FAIL;
3051 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3052 if (value == (int) s7_FAIL)
3055 sprintf (s7_err_msg,
3056 _("invalid constant: %d bit expression not in range %d..%d"),
3057 s7_score_df_range[data_type].bits,
3058 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3060 sprintf (s7_err_msg,
3061 _("invalid constant: %d bit expression not in range %d..%d"),
3062 s7_score_df_range[data_type - 24].bits,
3063 s7_score_df_range[data_type - 24].range[0], s7_score_df_range[data_type - 24].range[1]);
3064 s7_inst.error = s7_err_msg;
3065 return (int) s7_FAIL;
3068 if (data_type == _IMM5_RSHIFT_1)
3072 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
3077 if (s7_score_df_range[data_type].range[0] != 0)
3079 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3082 s7_inst.instruction |= value << shift;
3086 s7_inst.reloc.pc_rel = 0;
3093 s7_do_ldst_insn (char *str)
3105 s7_skip_whitespace (str);
3107 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3108 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3111 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
3115 s7_skip_whitespace (str);
3117 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3120 /* Conflicts can occur on stores as well as loads. */
3121 conflict_reg = (conflict_reg == reg);
3122 s7_skip_whitespace (str);
3123 temp = str + 1; /* The latter will process decimal/hex expression. */
3125 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
3132 /* ld/sw rD, [rA]+, simm12. */
3133 if (s7_skip_past_comma (&str) == s7_SUCCESS)
3135 if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
3136 || (s7_end_of_line (str) == (int) s7_FAIL))
3141 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3143 if ((ldst_func == INSN_LH)
3144 || (ldst_func == INSN_LHU)
3145 || (ldst_func == INSN_LW)
3146 || (ldst_func == INSN_LB)
3147 || (ldst_func == INSN_LBU))
3149 s7_inst.error = _("register same as write-back base");
3154 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3155 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3156 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
3158 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
3159 if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
3161 /* rs = r0-r7, offset = 4 */
3162 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3163 && (((s7_inst.instruction >> 3) & 0xfff) == 4))
3165 /* Relax to pophi. */
3166 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3168 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3170 (((s7_inst.instruction >> 15) & 0x7) << 4);
3175 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3177 (((s7_inst.instruction >> 15) & 0x7) << 4);
3179 s7_inst.relax_size = 2;
3184 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3187 s7_SET_INSN_ERROR (NULL);
3188 if (s7_end_of_line (str) == (int) s7_FAIL)
3194 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
3195 value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
3196 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3197 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3198 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3199 s7_inst.instruction |= value << 3;
3200 s7_inst.relax_inst = 0x8000;
3204 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3207 if (s7_end_of_line (str) == (int) s7_FAIL)
3210 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3211 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3212 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3214 /* lbu rd, [rs] -> lbu! rd, [rs] */
3215 if (ldst_idx == INSN_LBU)
3217 s7_inst.relax_inst = INSN16_LBU;
3219 else if (ldst_idx == INSN_LH)
3221 s7_inst.relax_inst = INSN16_LH;
3223 else if (ldst_idx == INSN_LW)
3225 s7_inst.relax_inst = INSN16_LW;
3227 else if (ldst_idx == INSN_SB)
3229 s7_inst.relax_inst = INSN16_SB;
3231 else if (ldst_idx == INSN_SH)
3233 s7_inst.relax_inst = INSN16_SH;
3235 else if (ldst_idx == INSN_SW)
3237 s7_inst.relax_inst = INSN16_SW;
3241 s7_inst.relax_inst = 0x8000;
3244 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
3245 if ((ldst_idx == INSN_LBU)
3246 || (ldst_idx == INSN_LH)
3247 || (ldst_idx == INSN_LW)
3248 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
3250 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3252 s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
3253 (((s7_inst.instruction >> 15) & 0xf) << 4);
3254 s7_inst.relax_size = 2;
3261 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3264 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3266 s7_inst.error = _("pre-indexed expression expected");
3270 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
3273 s7_skip_whitespace (str);
3276 s7_inst.error = _("missing ]");
3280 s7_skip_whitespace (str);
3281 /* ld/sw rD, [rA, simm12]+. */
3288 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3290 if ((ldst_func == INSN_LH)
3291 || (ldst_func == INSN_LHU)
3292 || (ldst_func == INSN_LW)
3293 || (ldst_func == INSN_LB)
3294 || (ldst_func == INSN_LBU))
3296 s7_inst.error = _("register same as write-back base");
3302 if (s7_end_of_line (str) == (int) s7_FAIL)
3305 if (s7_inst.reloc.exp.X_op == O_constant)
3307 unsigned int data_type;
3310 data_type = _SIMM12;
3312 data_type = _SIMM15;
3315 if ((dataptr != NULL)
3316 && (((strstr (dataptr, "0x")) != NULL)
3317 || ((strstr (dataptr, "0X")) != NULL)))
3320 if ((data_type != _SIMM16_LA)
3321 && (data_type != _VALUE_HI16)
3322 && (data_type != _VALUE_LO16)
3323 && (data_type != _IMM16)
3324 && (data_type != _IMM15)
3325 && (data_type != _IMM14)
3326 && (data_type != _IMM4)
3327 && (data_type != _IMM5)
3328 && (data_type != _IMM8)
3329 && (data_type != _SIMM12)
3330 && (data_type != _SIMM15)
3331 && (data_type != _IMM5_RSHIFT_1)
3332 && (data_type != _IMM5_RSHIFT_2)
3333 && (data_type != _SIMM14_NEG)
3334 && (data_type != _IMM10_RSHIFT_2))
3340 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3341 if (value == (int) s7_FAIL)
3344 sprintf (s7_err_msg,
3345 _("invalid constant: %d bit expression not in range %d..%d"),
3346 s7_score_df_range[data_type].bits,
3347 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3349 sprintf (s7_err_msg,
3350 _("invalid constant: %d bit expression not in range %d..%d"),
3351 s7_score_df_range[data_type - 24].bits,
3352 s7_score_df_range[data_type - 24].range[0],
3353 s7_score_df_range[data_type - 24].range[1]);
3354 s7_inst.error = s7_err_msg;
3358 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3359 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3360 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3361 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3363 s7_inst.instruction |= value << 3;
3365 s7_inst.instruction |= value;
3367 /* lw rD, [rA, simm15] */
3368 if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3370 /* Both rD and rA are in [r0 - r15]. */
3371 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3372 && (((s7_inst.instruction >> 20) & 0x10) == 0))
3374 /* simm15 = 0, lw -> lw!. */
3375 if ((s7_inst.instruction & 0x7fff) == 0)
3377 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3378 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3379 s7_inst.relax_size = 2;
3381 /* rA = r2, lw -> lwp!. */
3382 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3383 && ((s7_inst.instruction & 0x3) == 0)
3384 && ((s7_inst.instruction & 0x7fff) < 128))
3386 s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3387 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3388 s7_inst.relax_size = 2;
3392 s7_inst.relax_inst = 0x8000;
3397 s7_inst.relax_inst = 0x8000;
3400 /* sw rD, [rA, simm15] */
3401 else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3403 /* Both rD and rA are in [r0 - r15]. */
3404 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3406 /* simm15 = 0, sw -> sw!. */
3407 if ((s7_inst.instruction & 0x7fff) == 0)
3409 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3410 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3411 s7_inst.relax_size = 2;
3413 /* rA = r2, sw -> swp!. */
3414 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3415 && ((s7_inst.instruction & 0x3) == 0)
3416 && ((s7_inst.instruction & 0x7fff) < 128))
3418 s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3419 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3420 s7_inst.relax_size = 2;
3424 s7_inst.relax_inst = 0x8000;
3429 s7_inst.relax_inst = 0x8000;
3432 /* sw rD, [rA, simm15]+ sw pre. */
3433 else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3435 /* rA is in [r0 - r7], and simm15 = -4. */
3436 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3437 && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3439 /* sw -> pushhi!. */
3440 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3442 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3443 | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3444 s7_inst.relax_size = 2;
3449 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3450 | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3451 s7_inst.relax_size = 2;
3456 s7_inst.relax_inst = 0x8000;
3459 /* lh rD, [rA, simm15] */
3460 else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3462 /* Both rD and rA are in [r0 - r15]. */
3463 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3465 /* simm15 = 0, lh -> lh!. */
3466 if ((s7_inst.instruction & 0x7fff) == 0)
3468 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3469 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3470 s7_inst.relax_size = 2;
3472 /* rA = r2, lh -> lhp!. */
3473 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3474 && ((s7_inst.instruction & 0x1) == 0)
3475 && ((s7_inst.instruction & 0x7fff) < 64))
3477 s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3478 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3479 s7_inst.relax_size = 2;
3483 s7_inst.relax_inst = 0x8000;
3488 s7_inst.relax_inst = 0x8000;
3491 /* sh rD, [rA, simm15] */
3492 else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3494 /* Both rD and rA are in [r0 - r15]. */
3495 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3497 /* simm15 = 0, sh -> sh!. */
3498 if ((s7_inst.instruction & 0x7fff) == 0)
3500 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3501 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3502 s7_inst.relax_size = 2;
3504 /* rA = r2, sh -> shp!. */
3505 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3506 && ((s7_inst.instruction & 0x1) == 0)
3507 && ((s7_inst.instruction & 0x7fff) < 64))
3509 s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3510 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3511 s7_inst.relax_size = 2;
3515 s7_inst.relax_inst = 0x8000;
3520 s7_inst.relax_inst = 0x8000;
3523 /* lbu rD, [rA, simm15] */
3524 else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3526 /* Both rD and rA are in [r0 - r15]. */
3527 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3529 /* simm15 = 0, lbu -> lbu!. */
3530 if ((s7_inst.instruction & 0x7fff) == 0)
3532 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3533 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3534 s7_inst.relax_size = 2;
3536 /* rA = r2, lbu -> lbup!. */
3537 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3538 && ((s7_inst.instruction & 0x7fff) < 32))
3540 s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3541 | ((s7_inst.instruction & 0x7fff) << 3);
3542 s7_inst.relax_size = 2;
3546 s7_inst.relax_inst = 0x8000;
3551 s7_inst.relax_inst = 0x8000;
3554 /* sb rD, [rA, simm15] */
3555 else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3557 /* Both rD and rA are in [r0 - r15]. */
3558 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3560 /* simm15 = 0, sb -> sb!. */
3561 if ((s7_inst.instruction & 0x7fff) == 0)
3563 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3564 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3565 s7_inst.relax_size = 2;
3567 /* rA = r2, sb -> sb!. */
3568 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3569 && ((s7_inst.instruction & 0x7fff) < 32))
3571 s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3572 | ((s7_inst.instruction & 0x7fff) << 3);
3573 s7_inst.relax_size = 2;
3577 s7_inst.relax_inst = 0x8000;
3582 s7_inst.relax_inst = 0x8000;
3587 s7_inst.relax_inst = 0x8000;
3594 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3595 s7_inst.reloc.pc_rel = 0;
3601 s7_inst.error = s7_BAD_ARGS;
3607 s7_do_cache (char *str)
3609 s7_skip_whitespace (str);
3611 if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3619 cache_op = (s7_inst.instruction >> 20) & 0x1F;
3620 sprintf (s7_inst.name, "cache %d", cache_op);
3626 s7_skip_whitespace (str);
3628 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3631 s7_skip_whitespace (str);
3633 /* cache op, [rA] */
3634 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3636 s7_SET_INSN_ERROR (NULL);
3639 s7_inst.error = _("missing ]");
3644 /* cache op, [rA, simm15] */
3647 if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3652 s7_skip_whitespace (str);
3655 s7_inst.error = _("missing ]");
3660 if (s7_end_of_line (str) == (int) s7_FAIL)
3665 s7_inst.error = s7_BAD_ARGS;
3670 s7_do_crdcrscrsimm5 (char *str)
3675 s7_skip_whitespace (str);
3677 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3678 || s7_skip_past_comma (&str) == (int) s7_FAIL
3679 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3680 || s7_skip_past_comma (&str) == (int) s7_FAIL
3681 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3682 || s7_skip_past_comma (&str) == (int) s7_FAIL)
3685 /* cop1 cop_code20. */
3686 if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3691 if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3695 s7_end_of_line (str);
3698 /* Handle ldc/stc. */
3700 s7_do_ldst_cop (char *str)
3702 s7_skip_whitespace (str);
3704 if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3705 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3711 s7_skip_whitespace (str);
3713 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3716 s7_skip_whitespace (str);
3720 if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3723 s7_skip_whitespace (str);
3726 s7_inst.error = _("missing ]");
3731 s7_end_of_line (str);
3734 s7_inst.error = s7_BAD_ARGS;
3738 s7_do16_ldst_insn (char *str)
3740 s7_skip_whitespace (str);
3742 if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3750 s7_skip_whitespace (str);
3752 if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3755 s7_skip_whitespace (str);
3758 if (s7_end_of_line (str) == (int) s7_FAIL)
3762 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3763 | (((s7_inst.instruction >> 4) & 0xf) << 15);
3764 s7_inst.relax_size = 4;
3769 s7_inst.error = _("missing ]");
3774 s7_inst.error = s7_BAD_ARGS;
3778 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3781 s7_do16_ldst_imm_insn (char *str)
3783 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3785 char *dataptr = NULL, *pp = NULL;
3787 int assign_data = (int) s7_FAIL;
3788 unsigned int ldst_func;
3790 s7_skip_whitespace (str);
3792 if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3793 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3796 s7_skip_whitespace (str);
3799 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3801 data_exp[cnt] = *dataptr;
3806 data_exp[cnt] = '\0';
3811 ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3812 if (ldst_func == N16_LIU)
3813 assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3814 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3815 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3816 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3817 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3819 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3821 if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3825 if ((s7_inst.instruction & 0x7000) == N16_LIU)
3827 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3828 | ((s7_inst.instruction & 0xff) << 1);
3830 else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3831 || ((s7_inst.instruction & 0x7007) == N16_SHP))
3833 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3834 | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3836 else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3837 || ((s7_inst.instruction & 0x7007) == N16_SWP))
3839 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3840 | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3842 else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3843 || ((s7_inst.instruction & 0x7007) == N16_SBP))
3845 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3846 | (((s7_inst.instruction >> 3) & 0x1f));
3849 s7_inst.relax_size = 4;
3854 s7_do16_push_pop (char *str)
3859 s7_skip_whitespace (str);
3860 if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3861 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3867 /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3868 s7_inst.instruction &= ~(1 << 12);
3870 s7_inst.instruction |= H_bit_mask << 7;
3877 s7_skip_whitespace (str);
3878 if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3883 s7_inst.error = _("base register nums are over 3 bit");
3888 s7_skip_whitespace (str);
3889 if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3892 s7_inst.error = _("missing ]");
3898 if ((s7_inst.instruction & 0xf) == 0xa)
3902 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3903 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3907 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3908 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3916 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3917 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3921 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3922 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3925 s7_inst.relax_size = 4;
3929 s7_inst.error = s7_BAD_ARGS;
3933 /* Handle lcb/lcw/lce/scb/scw/sce. */
3935 s7_do_ldst_unalign (char *str)
3939 if (s7_university_version == 1)
3941 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3945 s7_skip_whitespace (str);
3947 /* lcb/scb [rA]+. */
3951 s7_skip_whitespace (str);
3953 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3960 s7_inst.error = _("missing +");
3966 s7_inst.error = _("missing ]");
3970 if (s7_end_of_line (str) == (int) s7_FAIL)
3973 /* lcw/lce/scb/sce rD, [rA]+. */
3976 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3977 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3982 s7_skip_whitespace (str);
3987 s7_skip_whitespace (str);
3988 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3993 /* Conflicts can occur on stores as well as loads. */
3994 conflict_reg = (conflict_reg == reg);
3995 s7_skip_whitespace (str);
3998 unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
4004 as_warn (_("%s register same as write-back base"),
4005 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4006 ? _("destination") : _("source")));
4011 s7_inst.error = _("missing +");
4015 if (s7_end_of_line (str) == (int) s7_FAIL)
4020 s7_inst.error = _("missing ]");
4026 s7_inst.error = s7_BAD_ARGS;
4032 /* Handle alw/asw. */
4035 s7_do_ldst_atomic (char *str)
4037 if (s7_university_version == 1)
4039 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4043 s7_skip_whitespace (str);
4045 if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4046 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4053 s7_skip_whitespace (str);
4058 s7_skip_whitespace (str);
4059 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4064 s7_skip_whitespace (str);
4067 s7_inst.error = _("missing ]");
4071 s7_end_of_line (str);
4074 s7_inst.error = s7_BAD_ARGS;
4079 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4080 int fix_num ATTRIBUTE_UNUSED,
4081 struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4082 symbolS *add_symbol)
4087 fixS *cur_fixp = NULL;
4089 struct s7_score_it inst_main;
4091 memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4093 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4094 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4095 inst_main.type = Insn_PIC;
4097 for (i = 0; i < var_num; i++)
4099 inst_main.relax_size += var_insts[i].size;
4100 var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4101 s7_GET_INSN_CLASS (var_insts[i].type));
4104 /* Check data dependency. */
4105 s7_handle_dependency (&inst_main);
4107 /* Start a new frag if frag_now is not empty. */
4108 if (frag_now_fix () != 0)
4110 if (!frag_now->tc_frag_data.is_insn)
4112 frag_wane (frag_now);
4118 /* Write fr_fix part. */
4119 p = frag_more (inst_main.size);
4120 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4122 if (inst_main.reloc.type != BFD_RELOC_NONE)
4123 fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4124 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4126 frag_now->tc_frag_data.fixp = fixp;
4127 cur_fixp = frag_now->tc_frag_data.fixp;
4130 dwarf2_emit_insn (inst_main.size);
4133 where = p - frag_now->fr_literal + inst_main.size;
4134 for (i = 0; i < var_num; i++)
4137 where += var_insts[i - 1].size;
4139 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4141 fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4142 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4143 var_insts[i].reloc.type);
4148 cur_fixp->fx_next = fixp;
4149 cur_fixp = cur_fixp->fx_next;
4153 frag_now->tc_frag_data.fixp = fixp;
4154 cur_fixp = frag_now->tc_frag_data.fixp;
4160 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4161 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4162 0, inst_main.size, 0), add_symbol, 0, NULL);
4164 /* Write fr_var part.
4165 no calling s7_gen_insn_frag, no fixS will be generated. */
4166 for (i = 0; i < var_num; i++)
4168 s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4169 p += var_insts[i].size;
4171 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4175 /* Build a relax frag for la instruction when generating s7_PIC,
4176 external symbol first and local symbol second. */
4179 s7_build_la_pic (int reg_rd, expressionS exp)
4181 symbolS *add_symbol = exp.X_add_symbol;
4182 offsetT add_number = exp.X_add_number;
4183 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4184 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4187 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4193 if (add_number == 0)
4198 /* For an external symbol, only one insn is generated;
4199 For a local symbol, two insns are generated. */
4201 For an external symbol: lw rD, <sym>($gp)
4202 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
4203 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4204 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4207 if (reg_rd == s7_PIC_CALL_REG)
4208 s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4209 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4212 For a local symbol :
4213 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4214 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4215 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4216 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4217 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4218 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4221 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4222 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4224 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4226 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4227 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4228 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4235 For an external symbol: addi rD, <constant> */
4236 sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4237 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4240 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4243 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
4244 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number);
4245 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4248 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4249 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4253 int hi = (add_number >> 16) & 0x0000FFFF;
4254 int lo = add_number & 0x0000FFFF;
4256 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4257 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4258 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4265 For an external symbol: ldis r1, HI%<constant> */
4266 sprintf (tmp, "ldis r1, %d", hi);
4267 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4270 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4273 For a local symbol: ldis r1, HI%<constant>
4274 but, if lo is outof 16 bit, make hi plus 1 */
4275 if ((lo < -0x8000) || (lo > 0x7fff))
4279 sprintf (tmp, "ldis_pic r1, %d", hi);
4280 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4283 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4284 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4290 For an external symbol: ori r1, LO%<constant> */
4291 sprintf (tmp, "ori r1, %d", lo);
4292 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4295 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4298 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4299 sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
4300 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4303 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4304 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4306 /* Insn 4: add rD, rD, r1 */
4307 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4308 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4311 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4321 s7_do_macro_la_rdi32 (char *str)
4325 s7_skip_whitespace (str);
4326 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4327 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4333 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4334 char *keep_data = str;
4336 /* Check immediate value. */
4337 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4339 s7_inst.error = _("expression error");
4342 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4343 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4345 s7_inst.error = _("value not in range [0, 0xffffffff]");
4352 /* la rd, simm16. */
4353 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4355 s7_end_of_line (str);
4358 /* la rd, imm32 or la rd, label. */
4361 s7_SET_INSN_ERROR (NULL);
4363 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4364 || (s7_end_of_line (str) == (int) s7_FAIL))
4370 if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4372 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4373 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4376 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4377 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4382 gas_assert (s7_inst.reloc.exp.X_add_symbol);
4383 s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4386 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4396 s7_do_macro_li_rdi32 (char *str)
4400 s7_skip_whitespace (str);
4401 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4402 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4408 char *keep_data = str;
4410 /* Check immediate value. */
4411 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4413 s7_inst.error = _("expression error");
4416 else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4417 && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4419 s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4426 /* li rd, simm16. */
4427 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4429 s7_end_of_line (str);
4435 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4439 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4440 || (s7_end_of_line (str) == (int) s7_FAIL))
4444 else if (s7_inst.reloc.exp.X_add_symbol)
4446 s7_inst.error = _("li rd label isn't correct instruction form");
4451 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4453 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4457 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4458 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4461 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4469 /* Handle mul/mulu/div/divu/rem/remu. */
4472 s7_do_macro_mul_rdrsrs (char *str)
4478 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4480 if (s7_university_version == 1)
4481 as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4483 strcpy (append_str, str);
4484 backupstr = append_str;
4485 s7_skip_whitespace (backupstr);
4486 if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4487 || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4488 || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4490 s7_inst.error = s7_BAD_ARGS;
4494 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4496 /* rem/remu rA, rB is error format. */
4497 if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4499 s7_SET_INSN_ERROR (s7_BAD_ARGS);
4503 s7_SET_INSN_ERROR (NULL);
4510 s7_SET_INSN_ERROR (NULL);
4511 if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4512 || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4518 char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4520 if (strcmp (s7_inst.name, "rem") == 0)
4522 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4523 sprintf (append_str1, "mfceh r%d", reg_rd);
4525 else if (strcmp (s7_inst.name, "remu") == 0)
4527 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4528 sprintf (append_str1, "mfceh r%d", reg_rd);
4532 sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4533 sprintf (append_str1, "mfcel r%d", reg_rd);
4536 /* Output mul/mulu or div/divu or rem/remu. */
4537 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4540 /* Output mfcel or mfceh. */
4541 if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4544 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4551 s7_exp_macro_ldst_abs (char *str)
4554 char *backupstr, *tmp;
4555 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4556 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4557 struct s7_score_it inst_backup;
4562 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4564 strcpy (verifystr, str);
4565 backupstr = verifystr;
4566 s7_skip_whitespace (backupstr);
4567 if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4571 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4575 sprintf (append_str, "li r1 %s", backupstr);
4576 s7_append_insn (append_str, TRUE);
4578 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4579 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4580 s7_do_ldst_insn (append_str);
4586 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4590 else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4592 const char *symname;
4593 const char *segname;
4595 /* Find out whether this symbol can be referenced off the $gp
4596 register. It can be if it is smaller than the -G size or if
4597 it is in the .sdata or .sbss section. Certain symbols can
4598 not be referenced off the $gp, although it appears as though
4600 symname = S_GET_NAME (sym);
4602 && (strcmp (symname, "eprol") == 0
4603 || strcmp (symname, "etext") == 0
4604 || strcmp (symname, "_gp") == 0
4605 || strcmp (symname, "edata") == 0
4606 || strcmp (symname, "_fbss") == 0
4607 || strcmp (symname, "_fdata") == 0
4608 || strcmp (symname, "_ftext") == 0
4609 || strcmp (symname, "end") == 0
4610 || strcmp (symname, GP_DISP_LABEL) == 0))
4614 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4615 /* We must defer this decision until after the whole file has been read,
4616 since there might be a .extern after the first use of this symbol. */
4618 && S_GET_VALUE (sym) == 0)
4619 || (S_GET_VALUE (sym) != 0
4620 && S_GET_VALUE (sym) <= s7_g_switch_value)))
4625 segname = segment_name (S_GET_SEGMENT (sym));
4626 return (strcmp (segname, ".sdata") != 0
4627 && strcmp (segname, ".sbss") != 0
4628 && strncmp (segname, ".sdata.", 7) != 0
4629 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4631 /* We are not optimizing for the $gp register. */
4636 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4637 external symbol first and local symbol second. */
4640 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4642 symbolS *add_symbol = exp.X_add_symbol;
4643 int add_number = exp.X_add_number;
4644 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4645 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4648 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4654 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4659 /* For an external symbol, two insns are generated;
4660 For a local symbol, three insns are generated. */
4662 For an external symbol: lw rD, <sym>($gp)
4663 (BFD_RELOC_SCORE_GOT15) */
4664 sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4665 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4668 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4671 For a local symbol :
4672 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4673 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4674 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4675 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4676 sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4677 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4680 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4681 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4683 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4684 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4685 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4688 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4693 s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4701 s7_do_macro_ldst_label (char *str)
4709 char *absolute_value;
4710 char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4711 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4712 struct s7_score_it inst_backup;
4713 struct s7_score_it inst_expand[3];
4714 struct s7_score_it inst_main;
4716 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4717 strcpy (verifystr, str);
4718 backup_str = verifystr;
4720 s7_skip_whitespace (backup_str);
4721 if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4724 if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4727 label_str = backup_str;
4729 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4730 if (*backup_str == '[')
4732 s7_inst.type = Rd_rvalueRs_preSI12;
4733 s7_do_ldst_insn (str);
4737 /* Ld/st rD, imm. */
4738 absolute_value = backup_str;
4739 s7_inst.type = Rd_rvalueRs_SI15;
4741 if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4743 s7_inst.error = _("expression error");
4746 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4747 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4749 s7_inst.error = _("value not in range [0, 0x7fffffff]");
4752 else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4754 s7_inst.error = _("end on line error");
4759 if (s7_inst.reloc.exp.X_add_symbol == 0)
4761 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4762 s7_exp_macro_ldst_abs (str);
4767 /* Ld/st rD, label. */
4768 s7_inst.type = Rd_rvalueRs_SI15;
4769 backup_str = absolute_value;
4770 if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4771 || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4777 if (s7_inst.reloc.exp.X_add_symbol == 0)
4780 s7_inst.error = s7_BAD_ARGS;
4785 if (s7_score_pic == s7_PIC)
4788 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4789 s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4790 s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4795 if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4796 && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4797 && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4801 /* Assign the real opcode. */
4802 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4803 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4804 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4805 s7_inst.instruction |= reg_rd << 20;
4806 s7_inst.instruction |= s7_GP << 15;
4807 s7_inst.relax_inst = 0x8000;
4808 s7_inst.relax_size = 0;
4814 /* Backup s7_inst. */
4815 memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4819 /* Determine which instructions should be output. */
4820 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4821 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4822 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4824 /* Generate three instructions.
4826 ld/st rd, [r1, 0] */
4827 for (i = 0; i < 3; i++)
4829 if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4832 memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4839 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4840 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4841 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4842 inst_main.type = Insn_GP;
4844 for (i = 0; i < 3; i++)
4845 inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4846 , s7_GET_INSN_CLASS (inst_expand[i].type));
4848 /* Check data dependency. */
4849 s7_handle_dependency (&inst_main);
4851 /* Start a new frag if frag_now is not empty. */
4852 if (frag_now_fix () != 0)
4854 if (!frag_now->tc_frag_data.is_insn)
4855 frag_wane (frag_now);
4861 /* Write fr_fix part. */
4862 p = frag_more (inst_main.size);
4863 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4865 if (inst_main.reloc.type != BFD_RELOC_NONE)
4867 s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4868 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4872 dwarf2_emit_insn (inst_main.size);
4875 /* s7_GP instruction can not do optimization, only can do relax between
4876 1 instruction and 3 instructions. */
4877 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4878 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4879 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4881 /* Write fr_var part.
4882 no calling s7_gen_insn_frag, no fixS will be generated. */
4883 s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4884 p += inst_expand[0].size;
4885 s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4886 p += inst_expand[1].size;
4887 s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4891 s7_gen_insn_frag (&inst_expand[0], NULL);
4892 s7_gen_insn_frag (&inst_expand[1], NULL);
4893 s7_gen_insn_frag (&inst_expand[2], NULL);
4897 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4902 s7_do_lw_pic (char *str)
4906 s7_skip_whitespace (str);
4907 if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4908 || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4909 || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4910 || (s7_end_of_line (str) == (int) s7_FAIL))
4916 if (s7_inst.reloc.exp.X_add_symbol == 0)
4919 s7_inst.error = s7_BAD_ARGS;
4924 s7_inst.instruction |= s7_GP << 15;
4925 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4930 s7_do_empty (char *str)
4933 if (s7_university_version == 1)
4935 if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4936 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4937 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4938 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4940 s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4944 if (s7_end_of_line (str) == (int) s7_FAIL)
4947 if (s7_inst.relax_inst != 0x8000)
4949 if (s7_inst.type == NO_OPD)
4951 s7_inst.relax_size = 2;
4955 s7_inst.relax_size = 4;
4961 s7_do_jump (char *str)
4965 s7_skip_whitespace (str);
4966 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4967 || s7_end_of_line (str) == (int) s7_FAIL)
4970 if (s7_inst.reloc.exp.X_add_symbol == 0)
4972 s7_inst.error = _("lacking label ");
4976 if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4977 && s7_inst.reloc.exp.X_add_number <= 16777215))
4979 s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4983 save_in = input_line_pointer;
4984 input_line_pointer = str;
4985 s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4986 s7_inst.reloc.pc_rel = 1;
4987 input_line_pointer = save_in;
4991 s7_do16_jump (char *str)
4993 s7_skip_whitespace (str);
4994 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4995 || s7_end_of_line (str) == (int) s7_FAIL)
4999 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5001 s7_inst.error = _("lacking label ");
5004 else if (!(s7_inst.reloc.exp.X_add_number >= 0
5005 && s7_inst.reloc.exp.X_add_number <= 4095))
5007 s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5011 s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5012 s7_inst.reloc.pc_rel = 1;
5016 s7_do_branch (char *str)
5018 unsigned long abs_value = 0;
5020 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5021 || s7_end_of_line (str) == (int) s7_FAIL)
5025 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5027 s7_inst.error = _("lacking label ");
5030 else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5031 && s7_inst.reloc.exp.X_add_number <= 524287))
5033 s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5037 s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5038 s7_inst.reloc.pc_rel = 1;
5040 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
5041 s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5043 /* Compute 16 bit branch instruction. */
5044 if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5046 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5047 s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5048 s7_inst.relax_size = 2;
5052 s7_inst.relax_inst = 0x8000;
5057 s7_do16_branch (char *str)
5059 if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5060 || s7_end_of_line (str) == (int) s7_FAIL))
5064 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5066 s7_inst.error = _("lacking label");
5068 else if (!(s7_inst.reloc.exp.X_add_number >= -512
5069 && s7_inst.reloc.exp.X_add_number <= 511))
5071 s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5075 s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5076 s7_inst.reloc.pc_rel = 1;
5077 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5081 /* Iterate over the base tables to create the instruction patterns. */
5084 s7_build_score_ops_hsh (void)
5087 static struct obstack insn_obstack;
5089 obstack_begin (&insn_obstack, 4000);
5090 for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5092 const struct s7_asm_opcode *insn = s7_score_insns + i;
5093 size_t len = strlen (insn->template_name);
5094 struct s7_asm_opcode *new_opcode;
5095 char *template_name;
5096 new_opcode = (struct s7_asm_opcode *)
5097 obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5098 template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5100 strcpy (template_name, insn->template_name);
5101 new_opcode->template_name = template_name;
5102 new_opcode->parms = insn->parms;
5103 new_opcode->value = insn->value;
5104 new_opcode->relax_value = insn->relax_value;
5105 new_opcode->type = insn->type;
5106 new_opcode->bitmask = insn->bitmask;
5107 hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5108 (void *) new_opcode);
5113 s7_build_dependency_insn_hsh (void)
5116 static struct obstack dependency_obstack;
5118 obstack_begin (&dependency_obstack, 4000);
5119 for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5121 const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5122 size_t len = strlen (tmp->insn_name);
5123 struct s7_insn_to_dependency *new_i2d;
5126 new_i2d = (struct s7_insn_to_dependency *)
5127 obstack_alloc (&dependency_obstack,
5128 sizeof (struct s7_insn_to_dependency));
5129 insn_name = (char *) obstack_alloc (&dependency_obstack, len + 1);
5131 strcpy (insn_name, tmp->insn_name);
5132 new_i2d->insn_name = insn_name;
5133 new_i2d->type = tmp->type;
5134 hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5140 s7_md_chars_to_number (char *buf, int n)
5143 unsigned char *where = (unsigned char *) buf;
5145 if (target_big_endian)
5150 result |= (*where++ & 255);
5158 result |= (where[n] & 255);
5165 /* Return true if the given symbol should be considered local for s7_PIC. */
5168 s7_pic_need_relax (symbolS *sym, asection *segtype)
5171 bfd_boolean linkonce;
5173 /* Handle the case of a symbol equated to another symbol. */
5174 while (symbol_equated_reloc_p (sym))
5178 /* It's possible to get a loop here in a badly written
5180 n = symbol_get_value_expression (sym)->X_add_symbol;
5186 symsec = S_GET_SEGMENT (sym);
5188 /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5190 if (symsec != segtype && ! S_IS_LOCAL (sym))
5192 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5195 /* The GNU toolchain uses an extension for ELF: a section
5196 beginning with the magic string .gnu.linkonce is a linkonce
5198 if (strncmp (segment_name (symsec), ".gnu.linkonce",
5199 sizeof ".gnu.linkonce" - 1) == 0)
5203 /* This must duplicate the test in adjust_reloc_syms. */
5204 return (!bfd_is_und_section (symsec)
5205 && !bfd_is_abs_section (symsec)
5206 && !bfd_is_com_section (symsec)
5209 /* A global or weak symbol is treated as external. */
5210 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5211 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5217 s7_judge_size_before_relax (fragS * fragp, asection *sec)
5221 if (s7_score_pic == s7_NO_PIC)
5222 change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5224 change = s7_pic_need_relax (fragp->fr_symbol, sec);
5228 /* Only at the first time determining whether s7_GP instruction relax should be done,
5229 return the difference between insntruction size and instruction relax size. */
5230 if (fragp->fr_opcode == NULL)
5232 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
5233 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
5234 return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
5242 s7_b32_relax_to_b16 (fragS * fragp)
5245 int relaxable_p = 0;
5246 int frag_addr = fragp->fr_address + fragp->insn_addr;
5248 addressT symbol_address = 0;
5251 unsigned long value;
5252 unsigned long abs_value;
5254 /* FIXME : here may be able to modify better .
5255 I don't know how to get the fragp's section ,
5256 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5257 is different from the symbol's. */
5259 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5261 s = fragp->fr_symbol;
5262 /* b/bl immediate */
5267 if (s->bsym != NULL)
5268 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
5271 value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5273 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
5274 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
5275 if ((offset & 0x80000) == 0x80000)
5276 offset |= 0xfff00000;
5278 abs_value = offset + symbol_address - frag_addr;
5279 if ((abs_value & 0x80000000) == 0x80000000)
5280 abs_value = 0xffffffff - abs_value + 1;
5282 /* Relax branch 32 to branch 16. */
5283 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
5284 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
5290 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
5291 fragp->fr_opcode = NULL;
5292 fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
5299 s7_parse_pce_inst (char *insnstr)
5304 char first[s7_MAX_LITERAL_POOL_SIZE];
5305 char second[s7_MAX_LITERAL_POOL_SIZE];
5306 struct s7_score_it pec_part_1;
5308 /* Get first part string of PCE. */
5309 p = strstr (insnstr, "||");
5312 strcpy (first, insnstr);
5314 /* Get second part string of PCE. */
5319 s7_parse_16_32_inst (first, FALSE);
5323 memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5332 s7_parse_16_32_inst (second, FALSE);
5336 if ( ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
5337 || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
5338 || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
5340 s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5341 strcpy (s7_inst.str, insnstr);
5346 s7_gen_insn_frag (&pec_part_1, &s7_inst);
5352 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5355 int len = strlen (r->name) + 2;
5356 char *buf = XNEWVEC (char, len);
5357 char *buf2 = XNEWVEC (char, len);
5359 strcpy (buf + i, r->name);
5360 for (i = 0; buf[i]; i++)
5362 buf2[i] = TOUPPER (buf[i]);
5366 hash_insert (htab, buf, (void *) r);
5367 hash_insert (htab, buf2, (void *) r);
5371 s7_build_reg_hsh (struct s7_reg_map *map)
5373 const struct s7_reg_entry *r;
5375 if ((map->htab = hash_new ()) == NULL)
5377 as_fatal (_("virtual memory exhausted"));
5379 for (r = map->names; r->name != NULL; r++)
5381 s7_insert_reg (r, map->htab);
5387 /* If we change section we must dump the literal pool first. */
5389 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5391 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5392 demand_empty_rest_of_line ();
5396 s7_s_score_text (int ignore)
5398 obj_elf_text (ignore);
5399 record_alignment (now_seg, 2);
5403 s7_s_section (int ignore)
5405 obj_elf_section (ignore);
5406 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5407 record_alignment (now_seg, 2);
5412 s7_s_change_sec (int sec)
5417 /* The ELF backend needs to know that we are changing sections, so
5418 that .previous works correctly. We could do something like check
5419 for an obj_section_change_hook macro, but that might be confusing
5420 as it would not be appropriate to use it in the section changing
5421 functions in read.c, since obj-elf.c intercepts those. FIXME:
5422 This should be cleaner, somehow. */
5423 obj_elf_section_change_hook ();
5428 seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5429 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5430 if (strcmp (TARGET_OS, "elf") != 0)
5431 record_alignment (seg, 4);
5432 demand_empty_rest_of_line ();
5435 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5436 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5437 if (strcmp (TARGET_OS, "elf") != 0)
5438 record_alignment (seg, 4);
5439 demand_empty_rest_of_line ();
5445 s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5449 if (s7_cur_proc_ptr == NULL)
5451 as_warn (_(".mask outside of .ent"));
5452 demand_empty_rest_of_line ();
5455 if (get_absolute_expression_and_terminator (&mask) != ',')
5457 as_warn (_("Bad .mask directive"));
5458 --input_line_pointer;
5459 demand_empty_rest_of_line ();
5462 off = get_absolute_expression ();
5463 s7_cur_proc_ptr->reg_mask = mask;
5464 s7_cur_proc_ptr->reg_offset = off;
5465 demand_empty_rest_of_line ();
5469 s7_get_symbol (void)
5475 c = get_symbol_name (&name);
5476 p = (symbolS *) symbol_find_or_make (name);
5477 (void) restore_line_pointer (c);
5482 s7_get_number (void)
5487 if (*input_line_pointer == '-')
5489 ++input_line_pointer;
5492 if (!ISDIGIT (*input_line_pointer))
5493 as_bad (_("expected simple number"));
5494 if (input_line_pointer[0] == '0')
5496 if (input_line_pointer[1] == 'x')
5498 input_line_pointer += 2;
5499 while (ISXDIGIT (*input_line_pointer))
5502 val |= hex_value (*input_line_pointer++);
5504 return negative ? -val : val;
5508 ++input_line_pointer;
5509 while (ISDIGIT (*input_line_pointer))
5512 val |= *input_line_pointer++ - '0';
5514 return negative ? -val : val;
5517 if (!ISDIGIT (*input_line_pointer))
5519 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5520 as_warn (_("invalid number"));
5523 while (ISDIGIT (*input_line_pointer))
5526 val += *input_line_pointer++ - '0';
5528 return negative ? -val : val;
5531 /* The .aent and .ent directives. */
5534 s7_s_score_ent (int aent)
5539 symbolP = s7_get_symbol ();
5540 if (*input_line_pointer == ',')
5541 ++input_line_pointer;
5543 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5546 #ifdef BFD_ASSEMBLER
5547 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5552 if (now_seg != data_section && now_seg != bss_section)
5558 as_warn (_(".ent or .aent not in text section."));
5559 if (!aent && s7_cur_proc_ptr)
5560 as_warn (_("missing .end"));
5563 s7_cur_proc_ptr = &s7_cur_proc;
5564 s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5565 s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5566 s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5567 s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5568 s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5569 s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5570 s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5571 s7_cur_proc_ptr->isym = symbolP;
5572 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5574 if (debug_type == DEBUG_STABS)
5575 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5577 demand_empty_rest_of_line ();
5581 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5588 backupstr = input_line_pointer;
5591 if (s7_cur_proc_ptr == NULL)
5593 as_warn (_(".frame outside of .ent"));
5594 demand_empty_rest_of_line ();
5597 s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5599 s7_skip_past_comma (&backupstr);
5600 while (*backupstr != ',')
5602 str[i] = *backupstr;
5610 s7_skip_past_comma (&backupstr);
5611 s7_cur_proc_ptr->frame_offset = val;
5612 s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5615 s7_skip_past_comma (&backupstr);
5617 while (*backupstr != '\n')
5619 str[i] = *backupstr;
5625 s7_cur_proc_ptr->leaf = val;
5627 s7_skip_past_comma (&backupstr);
5629 #endif /* OBJ_ELF */
5630 while (input_line_pointer != backupstr)
5631 input_line_pointer++;
5634 /* The .end directive. */
5637 s7_s_score_end (int x ATTRIBUTE_UNUSED)
5642 /* Generate a .pdr section. */
5643 segT saved_seg = now_seg;
5644 subsegT saved_subseg = now_subseg;
5648 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5650 p = s7_get_symbol ();
5651 demand_empty_rest_of_line ();
5656 #ifdef BFD_ASSEMBLER
5657 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5662 if (now_seg != data_section && now_seg != bss_section)
5669 as_warn (_(".end not in text section"));
5670 if (!s7_cur_proc_ptr)
5672 as_warn (_(".end directive without a preceding .ent directive."));
5673 demand_empty_rest_of_line ();
5678 gas_assert (S_GET_NAME (p));
5679 if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5680 as_warn (_(".end symbol does not match .ent symbol."));
5681 if (debug_type == DEBUG_STABS)
5682 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5685 as_warn (_(".end directive missing or unknown symbol"));
5687 if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5688 (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5689 (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5690 (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5691 (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5695 (void) frag_now_fix ();
5696 gas_assert (s7_pdr_seg);
5697 subseg_set (s7_pdr_seg, 0);
5698 /* Write the symbol. */
5699 exp.X_op = O_symbol;
5700 exp.X_add_symbol = p;
5701 exp.X_add_number = 0;
5702 emit_expr (&exp, 4);
5703 fragp = frag_more (7 * 4);
5704 s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5705 s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5706 s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5707 s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5708 s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5709 s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5710 s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5711 subseg_set (saved_seg, saved_subseg);
5714 s7_cur_proc_ptr = NULL;
5717 /* Handle the .set pseudo-op. */
5720 s7_s_score_set (int x ATTRIBUTE_UNUSED)
5723 char name[s7_MAX_LITERAL_POOL_SIZE];
5724 char * orig_ilp = input_line_pointer;
5726 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5728 name[i] = (char) * input_line_pointer;
5730 ++input_line_pointer;
5735 if (strcmp (name, "nwarn") == 0)
5737 s7_warn_fix_data_dependency = 0;
5739 else if (strcmp (name, "fixdd") == 0)
5741 s7_fix_data_dependency = 1;
5743 else if (strcmp (name, "nofixdd") == 0)
5745 s7_fix_data_dependency = 0;
5747 else if (strcmp (name, "r1") == 0)
5751 else if (strcmp (name, "nor1") == 0)
5755 else if (strcmp (name, "optimize") == 0)
5759 else if (strcmp (name, "volatile") == 0)
5763 else if (strcmp (name, "pic") == 0)
5765 s7_score_pic = s7_PIC;
5769 input_line_pointer = orig_ilp;
5774 /* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the
5775 $gp register for the function based on the function address, which is in the register
5776 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5777 specially by the linker. The result is:
5778 ldis gp, %hi(GP_DISP_LABEL)
5779 ori gp, %low(GP_DISP_LABEL)
5780 add gp, gp, .cpload argument
5781 The .cpload argument is normally r29. */
5784 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5787 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5789 /* If we are not generating s7_PIC code, .cpload is ignored. */
5790 if (s7_score_pic == s7_NO_PIC)
5796 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5799 demand_empty_rest_of_line ();
5801 sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5802 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5805 sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5806 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5809 sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5810 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5814 /* Handle the .cprestore pseudo-op. This stores $gp into a given
5815 offset from $sp. The offset is remembered, and after making a s7_PIC
5816 call $gp is restored from that location. */
5819 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5822 int cprestore_offset;
5823 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5825 /* If we are not generating s7_PIC code, .cprestore is ignored. */
5826 if (s7_score_pic == s7_NO_PIC)
5832 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5833 || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5838 cprestore_offset = get_absolute_expression ();
5840 if (cprestore_offset <= 0x3fff)
5842 sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5843 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5853 sprintf (insn_str, "li r1, %d", cprestore_offset);
5854 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5857 sprintf (insn_str, "add r1, r1, r%d", reg);
5858 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5861 sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5862 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5868 demand_empty_rest_of_line ();
5871 /* Handle the .gpword pseudo-op. This is used when generating s7_PIC
5872 code. It generates a 32 bit s7_GP relative reloc. */
5875 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5880 /* When not generating s7_PIC code, this is treated as .word. */
5881 if (s7_score_pic == s7_NO_PIC)
5887 if (ex.X_op != O_symbol || ex.X_add_number != 0)
5889 as_bad (_("Unsupported use of .gpword"));
5890 ignore_rest_of_line ();
5893 s7_number_to_chars (p, (valueT) 0, 4);
5894 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5895 demand_empty_rest_of_line ();
5898 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
5899 tables in s7_PIC code. */
5902 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5905 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5907 /* If we are not generating s7_PIC code, .cpload is ignored. */
5908 if (s7_score_pic == s7_NO_PIC)
5914 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5918 demand_empty_rest_of_line ();
5920 /* Add $gp to the register named as an argument. */
5921 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5922 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5926 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5927 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
5932 else if ((SIZE) >= 4) \
5934 else if ((SIZE) >= 2) \
5943 s7_s_score_lcomm (int bytes_p)
5950 segT current_seg = now_seg;
5951 subsegT current_subseg = now_subseg;
5952 const int max_alignment = 15;
5954 segT bss_seg = bss_section;
5955 int needs_align = 0;
5957 c = get_symbol_name (&name);
5958 p = input_line_pointer;
5963 as_bad (_("expected symbol name"));
5964 discard_rest_of_line ();
5968 SKIP_WHITESPACE_AFTER_NAME ();
5970 /* Accept an optional comma after the name. The comma used to be
5971 required, but Irix 5 cc does not generate it. */
5972 if (*input_line_pointer == ',')
5974 ++input_line_pointer;
5978 if (is_end_of_line[(unsigned char)*input_line_pointer])
5980 as_bad (_("missing size expression"));
5984 if ((temp = get_absolute_expression ()) < 0)
5986 as_warn (_("BSS length (%d) < 0 ignored"), temp);
5987 ignore_rest_of_line ();
5991 #if defined (TC_SCORE)
5992 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
5994 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
5995 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
5997 bss_seg = subseg_new (".sbss", 1);
5998 seg_info (bss_seg)->bss = 1;
5999 #ifdef BFD_ASSEMBLER
6000 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6001 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6008 if (*input_line_pointer == ',')
6010 ++input_line_pointer;
6013 if (is_end_of_line[(unsigned char)*input_line_pointer])
6015 as_bad (_("missing alignment"));
6020 align = get_absolute_expression ();
6027 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6029 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6031 record_alignment (bss_seg, align);
6038 /* Convert to a power of 2. */
6043 for (i = 0; align != 0; align >>= 1, ++i)
6049 if (align > max_alignment)
6051 align = max_alignment;
6052 as_warn (_("alignment too large; %d assumed"), align);
6057 as_warn (_("alignment negative; 0 assumed"));
6060 record_alignment (bss_seg, align);
6064 /* Assume some objects may require alignment on some systems. */
6065 #if defined (TC_ALPHA) && ! defined (VMS)
6068 align = ffs (temp) - 1;
6069 if (temp % (1 << align))
6076 symbolP = symbol_find_or_make (name);
6080 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6081 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6082 #ifdef BFD_ASSEMBLER
6083 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6084 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6086 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6089 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6093 subseg_set (bss_seg, 1);
6096 frag_align (align, 0, 0);
6098 /* Detach from old frag. */
6099 if (S_GET_SEGMENT (symbolP) == bss_seg)
6100 symbol_get_frag (symbolP)->fr_symbol = NULL;
6102 symbol_set_frag (symbolP, frag_now);
6103 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6107 S_SET_SEGMENT (symbolP, bss_seg);
6110 /* The symbol may already have been created with a preceding
6111 ".globl" directive -- be careful not to step on storage class
6112 in that case. Otherwise, set it to static. */
6113 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6115 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6117 #endif /* OBJ_COFF */
6120 S_SET_SIZE (symbolP, temp);
6124 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6126 subseg_set (current_seg, current_subseg);
6128 demand_empty_rest_of_line ();
6140 if ((s7_score_ops_hsh = hash_new ()) == NULL)
6141 as_fatal (_("virtual memory exhausted"));
6143 s7_build_score_ops_hsh ();
6145 if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6146 as_fatal (_("virtual memory exhausted"));
6148 s7_build_dependency_insn_hsh ();
6150 for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6151 s7_build_reg_hsh (s7_all_reg_maps + i);
6153 /* Initialize dependency vector. */
6154 s7_init_dependency_vector ();
6156 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6158 subseg = now_subseg;
6159 s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6160 (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6161 (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
6162 subseg_set (seg, subseg);
6164 if (s7_USE_GLOBAL_POINTER_OPT)
6165 bfd_set_gp_size (stdoutput, s7_g_switch_value);
6169 s7_assemble (char *str)
6172 know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6174 memset (&s7_inst, '\0', sizeof (s7_inst));
6175 if (s7_INSN_IS_PCE_P (str))
6176 s7_parse_pce_inst (str);
6178 s7_parse_16_32_inst (str, TRUE);
6181 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6184 /* We handle all bad expressions here, so that we can report the faulty
6185 instruction in the error message. */
6188 s7_operand (expressionS * exp)
6190 if (s7_in_my_get_expression)
6192 exp->X_op = O_illegal;
6193 if (s7_inst.error == NULL)
6195 s7_inst.error = _("bad expression");
6200 /* Turn a string in input_line_pointer into a floating point constant
6201 of type TYPE, and store the appropriate bytes in *LITP. The number
6202 of LITTLENUMS emitted is stored in *SIZEP. An error message is
6203 returned, or NULL on OK.
6205 Note that fp constants aren't represent in the normal way on the ARM.
6206 In big endian mode, things are as expected. However, in little endian
6207 mode fp constants are big-endian word-wise, and little-endian byte-wise
6208 within the words. For example, (double) 1.1 in big endian mode is
6209 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6210 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6213 s7_atof (int type, char *litP, int *sizeP)
6216 LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
6242 return _("bad call to MD_ATOF()");
6245 t = atof_ieee (input_line_pointer, type, words);
6247 input_line_pointer = t;
6250 if (target_big_endian)
6252 for (i = 0; i < prec; i++)
6254 s7_number_to_chars (litP, (valueT) words[i], 2);
6260 for (i = 0; i < prec; i += 2)
6262 s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6263 s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6271 /* Implementation of md_frag_check.
6272 Called after md_convert_frag(). */
6275 s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6277 know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6280 /* Implementation of TC_VALIDATE_FIX.
6281 Called before md_apply_fix() and after md_convert_frag(). */
6284 s7_validate_fix (fixS *fixP)
6286 fixP->fx_where += fixP->fx_frag->insn_addr;
6290 s7_force_relocation (struct fix *fixp)
6294 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6295 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6296 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6297 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6298 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6299 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6308 s7_fix_adjustable (fixS * fixP)
6310 if (fixP->fx_addsy == NULL)
6314 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6315 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6319 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6320 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6321 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6322 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6331 s7_elf_final_processing (void)
6333 unsigned long val = E_SCORE_MACH_SCORE7;
6335 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6336 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6337 elf_elfheader (stdoutput)->e_flags |= val;
6339 if (s7_fix_data_dependency == 1)
6341 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6343 if (s7_score_pic == s7_PIC)
6345 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6349 /* In this function, we determine whether s7_GP instruction should do relaxation,
6350 for the label being against was known now.
6351 Doing this here but not in md_relax_frag() can induce iteration times
6352 in stage of doing relax. */
6355 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6357 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6358 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6359 return s7_judge_size_before_relax (fragp, sec);
6365 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6367 long stretch ATTRIBUTE_UNUSED)
6371 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
6372 int relaxable_p = 0;
6373 bfd_boolean word_align_p = FALSE;
6376 /* If the instruction address is odd, make it half word align first. */
6377 if ((fragp->fr_address) % 2 != 0)
6379 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6381 fragp->insn_addr = 1;
6386 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6388 /* Get instruction size and relax size after the last relaxation. */
6389 if (fragp->fr_opcode)
6390 insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6392 insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6394 /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine
6395 whether the s7_GP instruction should do relax. */
6396 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6397 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6401 if (fragp->insn_addr < 2)
6403 fragp->insn_addr += 2;
6408 fragp->insn_addr -= 2;
6413 if (fragp->fr_opcode)
6414 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6416 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6420 if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6421 s7_b32_relax_to_b16 (fragp);
6423 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6424 next_fragp = fragp->fr_next;
6425 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6427 next_fragp = next_fragp->fr_next;
6433 int n_relaxable_p = 0;
6435 if (next_fragp->fr_opcode)
6437 n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6441 n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6444 if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6445 s7_b32_relax_to_b16 (next_fragp);
6446 n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6453 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6459 else if (insn_size == 2)
6462 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6483 /* Make the 32 bit insturction word align. */
6486 fragp->insn_addr += 2;
6490 else if (insn_size == 2)
6502 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
6503 if (word_align_p == FALSE)
6505 if (insn_size % 4 == 0)
6515 fragp->insn_addr += 2;
6526 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6529 if (fragp->fr_opcode)
6531 fragp->fr_opcode = NULL;
6532 /* Guarantee estimate stage is correct. */
6533 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6534 fragp->fr_fix += fragp->insn_addr;
6538 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6539 /* Guarantee estimate stage is correct. */
6540 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6541 fragp->fr_fix += fragp->insn_addr;
6546 if (fragp->fr_opcode)
6548 /* Guarantee estimate stage is correct. */
6549 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6550 fragp->fr_fix += fragp->insn_addr;
6554 /* Guarantee estimate stage is correct. */
6555 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6556 fragp->fr_fix += fragp->insn_addr;
6565 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6566 segT sec ATTRIBUTE_UNUSED,
6574 r_old = s7_RELAX_OLD (fragp->fr_subtype);
6575 r_new = s7_RELAX_NEW (fragp->fr_subtype);
6577 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6578 if (fragp->fr_opcode == NULL)
6580 memcpy (backup, fragp->fr_literal, r_old);
6581 fragp->fr_fix = r_old;
6585 memcpy (backup, fragp->fr_literal + r_old, r_new);
6586 fragp->fr_fix = r_new;
6589 fixp = fragp->tc_frag_data.fixp;
6590 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6592 if (fragp->fr_opcode)
6594 fixp = fixp->fx_next;
6596 while (fixp && fixp->fx_frag == fragp)
6598 if (fragp->fr_opcode)
6599 fixp->fx_where -= r_old + fragp->insn_addr;
6602 fixp = fixp->fx_next;
6605 if (fragp->insn_addr)
6607 s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6609 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6610 fragp->fr_fix += fragp->insn_addr;
6614 s7_pcrel_from (fixS * fixP)
6619 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6620 && (fixP->fx_subsy == NULL))
6626 retval = fixP->fx_where + fixP->fx_frag->fr_address;
6632 /* Round up a section size to the appropriate boundary. */
6634 s7_section_align (segT segment, valueT size)
6636 int align = bfd_get_section_alignment (stdoutput, segment);
6638 return ((size + (1 << align) - 1) & -(1 << align));
6642 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6644 offsetT value = *valP;
6645 offsetT abs_value = 0;
6648 unsigned short HI, LO;
6650 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6652 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6653 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6655 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6659 /* If this symbol is in a different section then we need to leave it for
6660 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
6661 so we have to undo it's effects here. */
6664 if (fixP->fx_addsy != NULL
6665 && S_IS_DEFINED (fixP->fx_addsy)
6666 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6667 value += md_pcrel_from (fixP);
6670 /* Remember value for emit_reloc. */
6671 fixP->fx_addnumber = value;
6673 switch (fixP->fx_r_type)
6675 case BFD_RELOC_HI16_S:
6677 { /* For la rd, imm32. */
6678 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6679 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
6680 newval |= (HI & 0x3fff) << 1;
6681 newval |= ((HI >> 14) & 0x3) << 16;
6682 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6685 case BFD_RELOC_LO16:
6686 if (fixP->fx_done) /* For la rd, imm32. */
6688 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6689 LO = (value) & 0xffff;
6690 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
6691 newval |= ((LO >> 14) & 0x3) << 16;
6692 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6695 case BFD_RELOC_SCORE_JMP:
6697 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6698 value = fixP->fx_offset;
6699 if (!(value >= 0 && value <= 0x1ffffff))
6701 as_bad_where (fixP->fx_file, fixP->fx_line,
6702 _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value);
6705 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6706 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6709 case BFD_RELOC_SCORE_BRANCH:
6710 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6711 value = fixP->fx_offset;
6715 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6716 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6718 if ((value & 0x80000000) == 0x80000000)
6719 abs_value = 0xffffffff - value + 1;
6720 if ((abs_value & 0xffffff00) != 0)
6722 as_bad_where (fixP->fx_file, fixP->fx_line,
6723 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6726 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6728 content = (content & 0xff00) | ((value >> 1) & 0xff);
6729 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6730 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6735 if ((value & 0x80000000) == 0x80000000)
6736 abs_value = 0xffffffff - value + 1;
6737 if ((abs_value & 0xfff80000) != 0)
6739 as_bad_where (fixP->fx_file, fixP->fx_line,
6740 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6741 (unsigned int) value);
6744 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6745 content &= 0xfc00fc01;
6746 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6747 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6750 case BFD_RELOC_SCORE16_JMP:
6751 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6753 value = fixP->fx_offset;
6754 if (!(value >= 0 && value <= 0xfff))
6756 as_bad_where (fixP->fx_file, fixP->fx_line,
6757 _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value);
6760 value = fixP->fx_offset & 0xfff;
6761 content = (content & 0xfc01) | (value & 0xffe);
6762 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6764 case BFD_RELOC_SCORE16_BRANCH:
6765 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6766 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6768 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6769 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6770 value = fixP->fx_offset;
6774 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6776 as_bad_where (fixP->fx_file, fixP->fx_line,
6777 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6778 (unsigned int) value);
6781 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6782 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6783 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6784 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6790 /* In different section. */
6791 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6792 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6793 value = fixP->fx_offset;
6797 if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6799 as_bad_where (fixP->fx_file, fixP->fx_line,
6800 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"),
6801 (unsigned int) value);
6804 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6805 content = (content & 0xff00) | ((value >> 1) & 0xff);
6806 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6810 if (fixP->fx_done || fixP->fx_pcrel)
6811 s7_number_to_chars (buf, value, 1);
6815 value = fixP->fx_offset;
6816 s7_number_to_chars (buf, value, 1);
6822 if (fixP->fx_done || fixP->fx_pcrel)
6823 s7_number_to_chars (buf, value, 2);
6827 value = fixP->fx_offset;
6828 s7_number_to_chars (buf, value, 2);
6834 if (fixP->fx_done || fixP->fx_pcrel)
6835 s7_number_to_chars (buf, value, 4);
6839 value = fixP->fx_offset;
6840 s7_number_to_chars (buf, value, 4);
6844 case BFD_RELOC_VTABLE_INHERIT:
6846 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6847 S_SET_WEAK (fixP->fx_addsy);
6849 case BFD_RELOC_VTABLE_ENTRY:
6852 case BFD_RELOC_SCORE_GPREL15:
6853 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6854 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6855 fixP->fx_r_type = BFD_RELOC_NONE;
6858 case BFD_RELOC_SCORE_GOT15:
6859 case BFD_RELOC_SCORE_DUMMY_HI16:
6860 case BFD_RELOC_SCORE_GOT_LO16:
6861 case BFD_RELOC_SCORE_CALL15:
6862 case BFD_RELOC_GPREL32:
6864 case BFD_RELOC_NONE:
6866 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6870 /* Translate internal representation of relocation info to BFD target format. */
6873 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6875 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
6877 bfd_reloc_code_real_type code;
6880 reloc = retval[0] = XNEW (arelent);
6883 reloc->sym_ptr_ptr = XNEW (asymbol *);
6884 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6885 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6886 reloc->addend = fixp->fx_offset;
6888 /* If this is a variant frag, we may need to adjust the existing
6889 reloc and generate a new one. */
6890 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6892 /* Update instruction imm bit. */
6897 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6898 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6899 off = fixp->fx_offset >> 16;
6900 newval |= (off & 0x3fff) << 1;
6901 newval |= ((off >> 14) & 0x3) << 16;
6902 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6904 buf += s7_INSN_SIZE;
6905 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6906 off = fixp->fx_offset & 0xffff;
6907 newval |= ((off & 0x3fff) << 1);
6908 newval |= (((off >> 14) & 0x3) << 16);
6909 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6911 retval[1] = XNEW (arelent);
6913 retval[1]->sym_ptr_ptr = XNEW (asymbol *);
6914 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6915 retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6917 retval[1]->addend = 0;
6918 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6919 gas_assert (retval[1]->howto != NULL);
6921 fixp->fx_r_type = BFD_RELOC_HI16_S;
6924 code = fixp->fx_r_type;
6925 switch (fixp->fx_r_type)
6930 code = BFD_RELOC_32_PCREL;
6934 case BFD_RELOC_HI16_S:
6935 case BFD_RELOC_LO16:
6936 case BFD_RELOC_SCORE_JMP:
6937 case BFD_RELOC_SCORE_BRANCH:
6938 case BFD_RELOC_SCORE16_JMP:
6939 case BFD_RELOC_SCORE16_BRANCH:
6940 case BFD_RELOC_VTABLE_ENTRY:
6941 case BFD_RELOC_VTABLE_INHERIT:
6942 case BFD_RELOC_SCORE_GPREL15:
6943 case BFD_RELOC_SCORE_GOT15:
6944 case BFD_RELOC_SCORE_DUMMY_HI16:
6945 case BFD_RELOC_SCORE_GOT_LO16:
6946 case BFD_RELOC_SCORE_CALL15:
6947 case BFD_RELOC_GPREL32:
6948 case BFD_RELOC_NONE:
6949 code = fixp->fx_r_type;
6952 type = _("<unknown>");
6953 as_bad_where (fixp->fx_file, fixp->fx_line,
6954 _("cannot represent %s relocation in this object file format"), type);
6958 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6959 if (reloc->howto == NULL)
6961 as_bad_where (fixp->fx_file, fixp->fx_line,
6962 _("cannot represent %s relocation in this object file format1"),
6963 bfd_get_reloc_code_name (code));
6966 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6967 vtable entry to be used in the relocation's section offset. */
6968 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6969 reloc->address = fixp->fx_offset;